- 不能使用短变量声明(Short Variable Declarations)这种方式来设置字段值:
structData.field := 111
会报错; - 关于 nil 的使用
- 不能使用nil初始化一个未指定类型的变量
- nil只能赋值给指针、channel、func、interface、map或slice类型的变量,赋值给其他类型会报错
- 不能直接使用nil值的Slice和Map
- map使用make分配内存时可指定capicity,但是不能对map使用cap函数
字符串不允许使用nil值
// var x = nil //error:不能使用nil初始化一个未指定类型的变量 // var x int = nil //error var x interface{} = nil //OK
数组用于函数传参时是值复制;注意:方法或函数调用时,传入参数都是值复制(跟赋值一致),除非是map、slice、channel、指针类型这些特殊类型是引用传递。
x := [3]int{1, 2, 3} func(arr [3]int) { arr[0] = 7 }(x) fmt.Println(x) // 123 func(arr *[3]int) { (*arr)[0] = 7 }(&x) // 或者之间使用slice传递 fmt.Println(x) // 723
- map中的key不存在时会获取到对应类型的零值,所以判断key是否存在应使用:
if _,ok := myMap["akey"]; !ok {}
- 字符串操作相关
- 不可修改,可转化为
[]byte
再修改;
- 不可修改,可转化为
- 字符串与
[]byte
之间的转换是复制(有内存损耗),可以用map[string][]byte
建立字符串与[]byte之间映射,也可range来避免内存分配来提高性能:for i,v := range []byte(str) {}
- 字符串与
- string的索引操作返回的是byte(或uint8),如想获取字符可使用for range,也可使用unicode/utf8包和exp/utf8string包的At()方法。
- 字符串并不总是UTF8的文本
- len(str)返回的是字符串的字节数,获取字符串的rune数是使用unicode/utf8.RuneCountInString()函数,但注意一些字符也可能是由多个rune组成,如é是两个rune组成。
使用for range迭代String,是以rune来迭代的。一个字符,也可以有多个rune组成。需要处理字符,尽量使用unicode/norm包。for range总是尝试将字符串解析成utf8的文本,对于它无法解析的字节,它会返回oxfffd的rune字符。因此,任何包含非utf8的文本,一定要先将其转换成字符切片([]byte)。
data := "A\xfe\x02\xff\x04" for _,v := range data { fmt.Printf("%#x ",v) } //prints: 0x41 0xfffd 0x2 0xfffd 0x4 (not ok) fmt.Println() for _,v := range []byte(data) { fmt.Printf("%#x ",v) } //prints: 0x41 0xfe 0x2 0xff 0x4 (good)
- 使用for range迭代map时每次迭代的顺序可能不一样,因为map的迭代是随机的。
- switch的case默认匹配规则不同于其它语言的是,匹配case条件后默认退出,除非使用fallthrough继续匹配;而其它语言是默认继续匹配,除非使用break退出匹配。
- 位运算的非操作是^(跟异或位运算一样),有别于其它语言的~。
- 位运算(与、或、异或、取反)优先级高于四则运算(加、减、乘、除、取余),有别于C语言。
- 结构体在序列化时非导出字段(以小写字母开头的字段名)不会被encode,因此在decode时这些非导出字段的值为”0值”
- 程序不等所有goroutine结束就会退出。可通过channel实现主协程(main goroutine)等待所有goroutine完成。
- channel 相关
- 对于无缓存区的channel,写入channel的goroutine会阻塞直到被读取,读取channel的goroutine会阻塞直到有数据写入。
- 从一个closed状态的channel读取数据是安全的,可通过返回状态(第二个返回参数)判断是否关闭;而向一个closed状态的channel写数据会导致panic。
- 向一个nil值(未用make分配空间)的channel发送或读取数据,会导致永远阻塞。
- 在Slice、Array、Map的多行书写最后的逗号不可省略,如果是单行可省;
- 方法接收者是类型(T),接收者只是原对象的值复制,在方法中修改接收者不会修改原始对象的值;如果方法接收者是指针类型(*T),是对原对象的引用,方法中对其修改当然是原对象修改。
- log包中的
log.Fatal和log.Panic不仅仅记录日志,还会中止程序
;它不同于Logging库。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。