这是我参与「第五届青训营 」笔记创作活动的第1天
第一部分:GO简介
GO语言特点:
1.高性能、高并发
2.语法简单
3.丰富的标准库
4.完善的工具链
5.静态链接
6.快速编译
7.跨平台
8.垃圾回收
第二部分:GO基础语法
运行GO代码方式
go run命令或者使用go build命令然后运行生成的可执行文件
变量声明与赋值
如上图,变量可以采用var a = "initial"方式声明并赋值,GO语言会自动识别变量类型或者在变量名称后自己指定变量类型;或者采用g := a + "foo"的方式声明并赋值变量g;常量定义可以指定类型也可以不指定类型,例如const s string = "constant"和const h = 50000
注意:
- GO语言没有字符变量,只有字符串变量
- GO语言的字符串用双引号定义,字符串可以使用+直接连接
if else
类似C、C++的if else结构,区别如下:
- GO语言的判断条件不需要在括号内,if后面直接跟判断条件,或者接一条语句然后接判断条件
- 花括号不能省略
for
GO语言去掉了while和do-while循环,只有for循环;for循环后面可以接三个条件,相当于C语言中的for循环。接一个条件相当于while循环。不跟条件的是死循环
switch
类似C语言的switch结构,区别如下:
- switch判断的变量不需要在括号内
- 判断的变量类型可以是int类型之外的其他类型
- case之后不需要接break语句,GO语言默认执行完case之后退出switch,而不是继续执行下去
- switch可以替换多次的if,switch后不接变量,case后接判断条件可以充当多个if判断,每次只进入一个case分支,处理完之后退出switch
array
定义数组:var a [5]int变量名称后跟数组大小以及数组内变量类型,默认初始化整型为0,字符串类型是空字符串。b := [5]int{1,2,3,4,5}定义整型数组的同时给元素赋值,未给出的元素按照默认初始化的规则初始化。二维数组类似C语言定义二维数组,只不过行列在变量名之后,var twoD [2][3]int
数组内元素赋值:a[4] = 100
slice
生成切片:s:= make([]string, 3)make函数传入两个参数,第一个参数:变量类型,第二个参数:切片长度,返回值:slice,map或者channel;
文档描述的make和new的区别:Like new, the first argument is a type, not a value. Unlike new, make's return type is the same as the type of its argument, not a pointer to it.
意思就是说,make返回值和传入的变量类型一致,而不是和new一样返回指向变量类型的指针类型
或者可以直接声明切片并赋值good L= []string{"g","oeee","o","d"}good变量类型是[]string,是切片类型
在切片尾部增加元素:s = append(s,"d")使用append函数,第一个参数:切片类型变量,第二个参数:要附加在尾部的元素,可以有多个元素;特殊的场景:允许把字符串类型的变量append到byte类型的切片后面,例如slice = append([]byte("hello "), "world"...)这个语句是合法的
map
生成map:
直接声明并默认初始化,整型、浮点型为0,字符串为空字符串m := make(map[string]int)
或者一边声明一边初始化m2 := map[string]int{"one":1,"two":2} 生成方式map\[键类型\]值类型
map遍历: 不会按照键排序也不会按照值排序,几乎纯随机
删除键值对: delete(m, "one")删除map m中键为one的键值对;打印删除掉的键值对不会报错,而是会创建一个默认初始化的键值对;打印整个map的时候删除的键值对不会出现
range
range一般和for结合使用,range提供了遍历切片类型的方式,例如:
for i, num := range nums {
sum += num
if num == 2 {
fmt.Println("index:", i, "num:", num) // index: 0 num: 2
}
}
i记录的是元素下标(对于map则记录键),num记录的是元素值
函数
定义函数方法:
func func_name(var1 type1, name2 type2, ... ) var_return_type {}或者
//返回的变量是多个
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
指针
和C、C++的指针相比功能减少很多,常用的是保证变量可以在函数内更改这个功能,例如:
func add2ptr(n *int) {
*n += 2
}
结构体
结构体定义方式:
type user struct {
name string
password string
}
结构体变量声明: 指定属性的方式a:=user{name:"123",password:"3333"}或者不指定属性的方式a:=user{"123","3333"}。允许部分初始化,其余默认初始化
结构体方法
在方法名前加上结构体修饰(u user)(结构体名 结构体类型)或者(u *user)让结构体在函数中可以被修改。修饰之后的方法可以通过结构体名.结构体方法的方式调用这个函数
错误处理
- 在函数的返回值里面可以加上错误处理的返回
- nil在GO语言表示空值或者零值,不同类型nil大小可能不一样并且nil不能比较
下划线作用总结:
-
用在返回值中:(比较常见)
v1, v2, _ := function(...)表示可以缺省一个返回值
-
用在变量中(接口断言):
例如我们定义了一个接口
type Foo interface{ Say() }又定义了一个结构体
type Dog struct{ }我们要在代码中判断Dog有没有实现Foo接口,可以这样
var _ Foo = Dog{},如果没有实现则编译报错。 -
用在import package:
在包名前加下划线表示执行本代码之前会先调用包中的初始化函数init,这种使用方式仅仅让导入的包初始化,而不使用其他功能。
字符串操作
a := "hello"
//检验是否含有
fmt.Println(strings.Contains(a, "ll")) // true
//计数
fmt.Println(strings.Count(a, "l")) // 2
//是否含有前缀
fmt.Println(strings.HasPrefix(a, "he")) // true
//是否含有后缀
fmt.Println(strings.HasSuffix(a, "llo")) // true
//查找子串起始位置索引
fmt.Println(strings.Index(a, "ll")) // 2
//用sep连接切片
fmt.Println(strings.Join([]string{"he", "llo", "221"}, "-")) // he-llo
//重复字符串
fmt.Println(strings.Repeat(a, 2)) // hellohello
//替换字符串,最后一个参数是替换的次数限制,如果<0表示没有次数限制
fmt.Println(strings.Replace(a, "e", "E", -1)) // hEllo
//把字符串按照sep分割成切片
fmt.Println(strings.Split("a-b-c", "-")) // [a b c]
//转换成小写
fmt.Println(strings.ToLower(a)) // hello
//转换成大写
fmt.Println(strings.ToUpper(a)) // HELLO
//获取长度
fmt.Println(len(a)) // 5
b := "你好啊!"
//中文字符的长度和英文字符长度不一样,中文的字符长度是3
fmt.Println(len(b)) // 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}
%v可以表示各种类型的变量,显示详细信息使用%+v,显示更详细的信息使用%#v
浮点数小数截断的方式类似C、C++的浮点数截断
json处理
json.Marshal(a)方法可以将结构体a转换成字符切片,调用string方法之后可以将字符切片变回json形式的字符串;函数的返回值是字符切片
对于json.MarshalIdent(a,"","\t")官方文档给出的例子如下:
Code:
data := map[string]int{ "a": 1, "b": 2, } b, err := json.MarshalIndent(data, "\<prefix>", "\<indent>") if err != nil { log.Fatal(err) } fmt.Println(string(b))Output:
{ \<prefix>\<indent>"a": 1, \<prefix>\<indent>"b": 2 \<prefix>}
json.UnMarshal(buf, &b)方法将buf字符切片的内容转换到结构体b中
时间处理
time.Now()获取当前时间
time.Date()设置时间变量,变量类型time.Time,变量依次是年、月、日、时、分、秒、纳秒、时间地点(一般是time.UTC)
时间变量.Year()可以获得年,类似的可以获得月、日等等
时间变量的差值可以使用Sub()方法计算,返回值是time.Duration类型的变量,该类型内置方法如下:
.Format()方法可以格式化时间的输出,
2006-01-02 15:04:05
是一个特殊的时间字符串,用来格式化时间输出
.Parse()方法可以将时间字符串按照第一个参数的格式更改并返回新的字符串
数字解析
strconv包提供了字符串转换成其他类型的方法,ParseFloat转换成浮点数,Atoi表示将字符串转换成整数,ParseInt第一个参数表示要转换的字符串,第二个参数表示进制,如果是0表示自动识别进制,第三个参数表示转换之后的变量存储大小(bitSize 位大小)
进程信息
os.Args可以打印出运行当前进程的参数,类型是[]string。第一个元素是build生成的可执行文件所在的临时文件夹,之后的元素是运行时的参数
os.GetEnv和os.SetEnv可以获取环境变量的键对应的值以及设置环境变量的键值对