随笔(一些需要注意的小细节)
int类型是一个特殊的类型,在64位电脑上占8个字节,在32位电脑上占4个字节
基本数据类型
布尔类型
- 布尔类型数据与整型数据不能进行交换
- 声明的布尔类型默认为<font color=red>false</font>
浮点型
- 浮点数字面量被自动类型推断为<font color=red>float64</font>类型
- 两个浮点数之间不应该使用==或!=进行比较操作,应该使用math标准库
复数类型
- 复数类型有两种:complex64和complex128,复数在计算机中由两个浮点数表示,一个实部一个虚部
- complex64:两个float32组成
- complex128:两个float64构成
- 三个内置函数:
- complex():构造一个复数
- real():返回一个复数实部
- image():返回复数虚部
字符串
- 字符串是常量,可以直接通过索引访问其字节单位,但是不能修改
- 字符串尾部<font color=red>不包含NULL字符</font>
-
基于字符串创建的切片和原字符串指向相同的底层字符数组,一样不能修改,对字符串的切片操作返回的子串仍是string,而非slice
rune类型
- Go内置两种字符类型:
- 一种是byte的字节类类型(byte是uint的别名)
- 一种是Unicode编码的字符rune(rune是int32的别名,占用四个字节)
- Go语言默认的字符编码就是UTF-8类型的,如果需要特殊的编码转换,则使用Unicode/UTF-8标准包
指针
- Go语言支持多级指针**T
- Go不支持指针运算
- 函数中允许返回局部变量的地址
- Go编译器使用<font color=red>栈逃逸</font>机制将这种局部变量的空间分配在堆上
func sum(a,b int) *int{ sum := a + b return &sum //sum将分配在堆上 }
- Go编译器使用<font color=red>栈逃逸</font>机制将这种局部变量的空间分配在堆上
切片
-
切片支持的操作
- 内置函数len()返回切片长度
- 内置函数cap()返回切片底层数组容量
- 内置函数append()对切片追加元素
- 内置函数copy()用于复制一个切片
-
切片:
为什么用切片:
1. 数组的容量固定,不能自动拓展。 2. 值传递。 数组作为函数参数时,将整个数组值拷贝一份给形参。 在Go语言当,我们几乎可以在所有的场景中,使用 切片替换数组使用。
切片的本质:
不是一个数组的指针,是一种数据结构体,用来操作数组内部元素。 runtime/slice.go type slice struct { *p len
切片的使用: cap
}
数组和切片定义区别:创建数组时 [ ] 指定数组长度。 创建切片时, [] 为空,或者 ... 切片名称 [ low : high : max ] low: 起始下标位置 high:结束下标位置 len = high - low 容量:cap = max - low 截取数组,初始化 切片时,没有指定切片容量时, 切片容量跟随原数组(切片)。 s[:high:max] : 从 0 开始,到 high结束。(不包含) s[low:] : 从low 开始,到 末尾 s[: high]: 从 0 开始,到 high结束。容量跟随原先容量。【常用】
切片创建:
1. 自动推导类型创建 切片。slice := []int {1, 2, 4, 6} 2. slice := make([]int, 长度,容量) 3. slice := make([]int, 长度) 创建切片时,没有指定容量, 容量== 长度。【常用】
切片做函数参数 —— 传引用。(传地址)
append:在切片末尾追加元素
append(切片对象, 待追加元素) 向切片增加元素时,切片的容量会自动增长。1024 以下时,一两倍方式增长。
copy:
copy(目标位置切片, 源切片) 拷贝过程中,直接对应位置拷贝。
-
map:
字典、映射 key —— value key: 唯一、无序。 不能是引用类型数据。
map 不能使用 cap()
创建方式:
1. var m1 map[int]string --- 不能存储数据2. m2 := map[int]string{} ---能存储数据 3. m3 := make(map[int]string) ---默认len = 0 4. m4 := make(map[int]string, 10)
初始化:
1. var m map[int]string = map[int]string{ 1: "aaa", 2:"bbb"} 保证key彼此不重复。 2. m := map[int]string{ 1: "aaa", 2:"bbb"}
赋值:
赋值过程中,如果新map元素的key与原map元素key 相同 ——> 覆盖(替换) 赋值过程中,如果新map元素的key与原map元素key 不同 ——> 添加
map的使用:
遍历map: for key值, value值 := range map { } for key值 := range map { } 判断map中key是否存在。 map[下标] 运算:返回两个值, 第一个表 value 的值,如果value不存在。 nil 第二个表 key是否存在的bool类型。存在 true, 不存在false
删除map:
delete()函数: 参1: 待删除元素的map 参2: key值 delete(map, key) 删除一个不存在的key , 不会报错。 map 做函数参数和返回值,传引用。
Switch
- 在switch中加入了一个<font color=red>fallthough</font>关键字,强制执行下一个case语句,不在判断下一个case子句的条件是否成立
- switch后面可以加入一个初始化语句,用分号隔开
switch i := "y"; i{ case "y": ··· }
函数
- 首字母大小写决定该函数在其他包是否可见:大写时其他包可见,小写时只有相同包可以访问
- 不支持默认值参数
- 不支持函数重载
- 不支持函数嵌套(除匿名函数外)
延迟调用函数---defer
- defer后面必须是函数或方法的调用
- defer函数的实参在注册时通过值拷贝传递进去
- defer函数的调用<font color=red>先进后出</font>
panic和recover
- panic用来主动抛出错误,recover用来捕获panic抛出的错误
panic(i interface{})
recover() interface{}
- panic的参数是一个空接口类型interface{},所以任意类型的变量都可以传递给panic
- 发生panic后,程序就会从调用panic的函数位置或者发生panic的地方立即返回,逐层向上执行函数的defer语句,然后逐层打印函数调用堆栈,直到recover捕获或运行到最外层函数而退出
- recover()用来捕获panic,阻止panic继续向上传递。
- recover和defer一起使用,但是recover只有在defer后面的函数体内才能被直接调用才能捕获panic终止异常,否则返回nil,异常继续向外传递
//这个会捕获失败
defer recover()
//这个才能调用成功
defer func(){
recover()
}
- 包中init函数引发的panic只能在init函数中捕获,在main函数中无法被捕获,原因是init函数先于main函数执行