1 基础语法
1.1 代码初体验 — Hello World
package main
import(
"fmt"
)
func main(){
fmt.Println("hello world")
}
1.2 变量
1.2.1 变量声明
- var 变量名 (变量类型) = 等于值
var a = "initial"
var b,c int = 1,2
- 变量名 := 等于值
d :=100
1.2.2 常量声明
- const 变量名 (变量类型) = 等于值
const e string = "constant"
1.3 if、for、which结构
1.3.1 if 语句
Go语言相较于C语言不同点:
if后面无括号
if后面必须接大括号
- 格式:
if xx {
执行1
}
else if xy{
执行2
}
else {
执行3
}
1.3.2 for循环
格式:
for initialization; condition; post{
// 循环中执行的代码块
}
其中,initialization 是循环变量的初始化语句,condition 是循环条件,post 是每次循环后执行的语句。这三个部分都可以省略
代码示例:
for i:=0; i<5; i++{
//continue继续循环
//break跳出循环
}
1.3.3 switch 语句
格式:
switch [定义变量;] [变量]{
case [条件/具体值]:
//代码
case [条件/具体值]:
//代码
default:
//代码
}
switch结构中某个最多只能执行一个case,使用fallthrough可以让下一个case/default继续执行
1.4 数组、切片
1.4.1 数组
数组是一组固定长度的数据项,它们具有相同的类型。数组的长度是在声明时指定的,不能更改。
var arr [num]type
1.4.2切片
切片是一个拥有相同类型元素的可变长度的序列。支持自动扩容。切片是一个引用类型,底层引用了一个数组,并且可以重新分配底层数组的大小。
var name []type
- 使用make()函数构造切片
make([]T,size,cap)
//T:切片的元素类型
//size:切片中元素的数量
//cap:切片的容量
- 基于数组定义切片
切片的底层就是一个数组,所以我们可以基于数组定义切片。
func main() {
// 基于数组定义切片
a := [5]int{55, 56, 57, 58, 59}
b := a[1:4] //基于数组a创建切片,包括元素a[1],a[2],a[3]
fmt.Println(b) //[56 57 58]
fmt.Printf("type of b:%T\n", b) //type of b:[]int
}
//还支持如下方式
//c := a[1:] [56 57 58 59]
//d := a[:4] [55 56 57]
//e := a[:] [55 56 57 58 59]
切片方法
- append():为切片添加元素
- copy():复制切片
- delete():
1.5 map、range
1.5.1 map
- map定义
map[KeyType]ValueType
//KeyType:键的类型
//ValueType:键对应的值的类型
map类型的变量默认初始值为nil,需要使用 make() 函数来分配内存,语法为:
make(map[KeyType]ValueType, [cap])
其中cap为map的容量,参数不是必须得,但应该在初始化map时就为其指定一个合适的容量。
- map的基本使用
map中的数据都是成对出现的,map的基本使用示例代码
func main(){
m :=make(map[string]int)
m["one"] = 1
m["two"] = 2
fmt.Println(m) //map[one:1 two:2]
fmt.Println(len(m)) // 2
fmt.Println(m["one"]) // 1
}
- 判断键存在
Go语言中有个判断map中键是否存在的特殊写法,格式如下:
value, ok := map[key]
- Map的遍历
map的遍历不会按照字母顺序和插入顺序,而是随机顺序。
func main() {
// for range遍历map
scoreMap := make(map[string]int)
scoreMap["张三"] = 90
scoreMap["小明"] = 100
scoreMap["娜扎"] = 60
//遍历Key和value
for k, v := range scoreMap {
fmt.Println(k, v)
}
//只遍历Key
for k:= range scoreMap{
fmt.Println(k);
}
}
- 键值对删除
delete(map,key)
代码实例:
func main() {
// 使用delete()函数删除键值对
scoreMap := make(map[string]int)
scoreMap["张三"] = 90
scoreMap["小明"] = 100
scoreMap["娜扎"] = 60
delete(scoreMap, "小明") //将小明:100从map中删除
delete(scoreMap, "栗子") //如果存在就删除,不存在就不操作,不报错
for k, v := range scoreMap {
fmt.Println(k, v)
}
}
range
Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。
for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。格式如下:
for key, value := range oldMap {
newMap[key] = value
}
以上代码中的 key 和 value 是可以省略。
只想读取key,格式如下:
for key:=range oldMap
//或者
for key,_:=range oldMap
只想读value,格式如下:
for _,value :=range oldMap
1.6 函数、指针
函数
Go 语言函数定义格式如下:
func function_name( [parameter list] ) [return_types] {
函数体
}
其中:
- func:函数由 func 开始声明
- function_name:函数名称,参数列表和返回值类型构成了函数签名。
- parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
- return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。
- 函数体:函数定义的代码集合。
在实际的业务逻辑代码里面几乎所有的函数都返回两个值,第一个是真正的返回结果,第二个值是一个错误信息
func exists(m map[string]string,k string) (v string, ok bool) {
v,ok = m[k]
return v, ok
}
指针
go语言中的指针支持的操作很有限,指针的一个主要用途是对于传入参数进行修改
- 代码实例
package main
import "fmt"
func add2ptr(n *int){
*n += 2
}
func main() {
n:=5
add2ptr(&n)
fmt.Println(n)
}
1.7 结构体
结构体
结构体的格式如下:
type struct_variable_type struct{
member definition
...
member definition
}
如果要访问结构体成员,需要使用点号 . 操作符,格式为:
结构体.成员名
结构体方法
- 定义
// 定义方法的语法格式:
func (接收者变量 接收者类型) 方法名(参数列表) (返回值列表){
//方法体
}
// 定义结构体
type point struct {
X int
Y int
}
// 定义结构体方法
func (p point) print() {
fmt.Println(p.X, p.Y)
}
1.8 错误处理
GO里预定义了一个error接口类型;错误值用来表示错误状态, 错误类型也是种数据类型,和其他数据类型一样,可以作为参数也可以作为返回值
type error interface {
Error() string
}
在Go语言中,可以在函数返回值中加err,代表函数可能返回错误。
//有错误时:
return nil,err //err可以通过errors.New()创建
//无错误时:
return n,nil
1.9 字符串
-
字符串操作
- strings.Contains( , ) :包含另一个字符串
- strings.Count( , ) :返回一个字符串有几个指定的字符串
- string.EqualFold( , ) :不区分大小写的字符串比较,区分的使用 == 就可以
- strings.Index( , ) :寻找字符串第一次出现的位置,没有的话返回-1
- strings.Replace(s,oldstr,newstr,n)将一个字符串中的字符串替换成另一个字符串,n表示替换几个,如果是-1表示替换所有
- strings.Split(s,str) 将一个字符串按照指的的分隔符分割为一个字符串数组
- strings.ToLower(s)、stings.ToUpper(s) 将字符串进行大小写的变化
-
字符串格式化
package main
import "fmt"
type point struct{
x, y int
}
func main() {
s:="hello"
n:=123
p:=point(1,2)
fmt. Println(s, n) // hello 123
fmt. Println(p) //{12 }
fmt. Printf("s=%v\n", s) // s=hello
fmt. Printf("n=%v\n", n) // n=123
fmt. Printf("p=%v\n", p) // p={1 2}
fmt. Printf("p=%+v\n", p) // p={x:1 y:2}
fmt. Printf("p=%#v\n", p) // p=main. point{x:1, y:2}
f := 3.141592653
fmt. Println(f) // 3.141592653
fmt. Printf("%.2f\n", f) // 3.14
}
1.10 JSON处理
- 编码为JSON格式
调用Go语言内置的encoding/json标准库中的json.Marshal()函数可以对一组数据进行JSON格式的编码。
buf,err := json.Marshal(a)
如果编码成功,err将赋于零值nil,变量buf将会是一个进行JSON格式化后的[]byte类型
- 解析JSON数据
可以使用json.Unmarshal()函数将JSON格式的文本解码为Go里面预期的数据结构。
err = json.Unmarshal(buf,&b)
- 首字母大小写问题
Go语言中首字母编码和解析都默认是大写,若要实现json化后属性名为小写,可以使用struct tag。
type userInfo struct{
Name string
Age int `json:"age"`
}
1.11 时间处理、数字解析
时间处理
获取当前时间 time.Now()
手动构造时间-time.Date(),构造时间可以使用.来获取具体时间数值,例如:t.Year()
获取当前时间戳 t.Unix()
计算时间差 t2.Sub(t1)
格式化时间 time.Format("具体格式")
数字解析
strconv 是 Golang 中一个非常常用的包,主要用于字符串和基本数据类型之间的相互转换。
- strconv.Atoi :Atoi 函数用于将字符串转换为 int 类型
- strconv.Parse
- 解析整数:strconv.ParseInt()
- 解析布尔值:strconv.ParseBool()
- 解析浮点数:strconv.ParseFloat()
package main
import(
"fmt"
"strconv"
)
func main() {
f, _ := strconv.ParseFloat("1.234",64)
N, _ := strconv.ParseInt("111",10,64)
// 111-字符串 10-进制 64-精度
n2, _ :=strconv.Atoi("123")
n2,err :=strconv.Atoi("AAA")
fmt.Println(n2,err)
//0 strconv.Atoi:parsing "AAA":invalid syntax
1.12 进程信息
go中通过os.Argv来得到程序执行时的指定命令行参数 os.Getenv获取环境变量,os.Setenv写入环境变量
理解与建议:go语言相较于其他语言更加简单,但如果要学好还是得要真正学习,还要不断拓展自己的知识面,要有精益求精的精神。作为一门编程语言,实践永远是必不可少的,所以学好够语言还是要做到理论与实践相结合。