这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天
一、本堂课重点内容
Go基础知识
- 变量 && 常量
声明方式:
var name [类型] = [值]
仅限函数内部:
name := 值
常量声明把var变成const就行,go里的常量没有确定类型,会根据上下文来自动确定类型
退化赋值的前提条件:最少有一个变量被定义,且处于同一作用域,例如:
func main() {
x := 100
fmt.Println(&x, x)//0xc00000e098 100
x, y := 200, "abe"
fmt.Println(&x, x)//0xc00000e098 200
fmt.Println(y)
}
- if-else
主要是与C++的区别:
- 不需要小括号
- 后面必须接左大括号
- 循环
只有for循环
最简单的for循环是在for后面什么都不写,代表一个死循环
也可以是经典的C for循环
continue 和 break含义与C中的一样
- switch
- 表达式不需要小括号
- case不会像C++那样没有break就一直向下走,可以认为每个case默认添加了break语句
- 表达式类型可以为任意类型甚至可以没有,switch可以替代任意一条if-else语句
- 数组
定义数组:
var a [5]int
b := [5]int{1,2,3,4,5}
因为数组的长度是不可变的,在实际工程中经常用切片
- 切片
切片可以任意更改长度,slice初始化时可以指定长度,创建切片:
section_name := make([]类型,len)
nums := []int{1, 2, 3}
var nums = []int{1, 2, 3}
使用append追加元素,必须把append的结果赋值给原数组,因为slice的原理实际上是它有一个它存储了一个长度和一个容量,加一个指向一个数组的指针,在执行append操作的时候,如果容量不够的话,会扩容并且返回新的slice
section_name = append(section_name,元素1,...)
切片操作时,前闭后开,以下输出下标[2,3,4)元素 不支持负数索引
section_name[2,5]
- &^
在C++中没有见过这个操作符 操作符 &^,按位置零,例如:z = x &^ y,表示如果 y 中的 bit 位为 1,则 z 对应 bit 位为 0,否则 z 对应 bit 位等于 x 中相应的 bit 位的值
- map
类似于C++中的unordered_map,go的map是完全无序的,遍历的时候不会按字母顺序,也不会按照插入的顺序输出,而是随机顺序。
创建map
map_name := make(map[key]val)
删除键值
delete(map_name,key)
- range
对于一个slice和一个map,可以用range来快速遍历
用range遍历时,对于数组会返回两个值,第一个是索引,第二个是对应位置的值,如果不需要索引的话,可以用下划线来忽略
- 函数
参数的类型可写可不写
返回值可以是多个,名字可写可不写
- 指针
主要用途就是对传入的参数进行修改
使用时跟C一样
- 结构体
带类型的字段的集合,声明结构体:
type struct_name struct{
n1 string
n2 int
...
}
初始化结构体变量,构造时需要传入每个字段的初始值,可以只对一部分字段进行初始化,用键值对的方式指定初始值
a := struct_name{n1:"mm",n2:2,...}
- JSON处理
对于一个已有的结构体,什么都不做,只要保证每个字段的首字母是大写的,也就是公开字段,那么这个结构体就可以用JSON.marshaler去序列化,变成一个JSON的字符串
序列化之后的字符串可以使用JSON.unmarshaler去反序列化到一个空的变量里
这样默认序列化出来的字符串,它的风格是大写字母开头,可以在后面用json tag等语法来修改josn结果里面的字段
实践练习例子
- secretNumber := rand.Intn(maxNum) 使用该函数生成随机数的时候,需要设置随机数种子,否则每一次生成都会生成相同的随机数序列。一般在程序开始时,用启动的时间戳初始化随机数种子
maxNum := 100
rand.Seed(time.Now().UnixNano())
secretNumber := rand.Intn(maxNum)
- 程序每次开始时都会打开几个文件,如stdin,stdout,stderr等, 直接操作stdin文件很不方便,先用函数把一个文件转化成一个reader变量(流), reader变量上有很多用来操作流的操作
- defer程序结束后,从下往上依次执行每个defer