Slice 和 Array 维度是一维
级别:新手入门级
Go 看上去支持多维的 Array 和 Slice,但是其实不然。尽管可以创建 Array 的 Array,也可以创建 Slice 的 Slice。对于依赖多维 Array 的计算密集型的程序,无论是从性能还是复杂程度,Go 都不是最佳选择。
当然,如果你选择创建嵌套的 Array 与嵌套的 Slice,那么你就得自己负责进行索引、进行下表检查、以及 Array 增长时的内存分配。嵌套 Slice 分为两种,Slice 中嵌套独立的 Slice,或者 Slice 中嵌套共享数据的 Slice。
使用嵌套的独立 Slice 创建多维的 Array 需要两步。第一步,创建外围 Slice,然后分配每个内部的 Slice。内部的 Slice 是独立的,可以对每个单独的内部 Slice 进行缩放。
|
|
使用嵌套、共享数据的 Slice 创建多维 Array 需要三步。第一,创建数据“容器”,第二部,创建外围 Slice,第三部,对内部的 Slice 进行初始化。
|
|
Go 语言也有对于支持多维 Array 和 Slice 的提案,不过不要期待太多。Go 语言官方将这些需求分在“低优先级”组中。
试图访问不存在的 Map 键值
级别:新手入门级
并不能在所有情况下都能通过判断 map 的记录值是不是 nil 判断记录是否存在。在 Go 语言中,对于“零值”是 nil 的数据类型可以这样判断,但是其他的数据类型不可以。简而言之,这种做法并不可靠(例如布尔变量的“零值”是 false)。最可靠的做法是检查 map 记录的第二返回值。
错误代码:
|
|
修正代码:
|
|
String 不可变
级别:新手入门级
对于 String 中单个字符的操作会导致编译失败。String 是带有一些附加属性的只读的字节片(Byte Slices)。所以如果想要对 String 操作的话,应当使用字节片操作,而不是将它转换为 String 类型。
错误信息:
|
|
错误信息:
|
|
修正代码:
|
|
注意这里的操作并不就是最正确的操作,因为有些字符可能会存储在多个字节中。如果你的开发情景有这种情况的话,需要先把 String 转换为 rune 格式。即便是 rune,一个字符也可能会保存在多个 rune 中,因此 Go String 也表现为字节序列(String Sequences)。Rune 一般理解为“字符”,“一个字符也可能会保存在多个 rune 中”的情况我们将会在下面提到。
String 与 Byte Slice 的转换
级别:新手入门级
当将 String 类型和 Byte Slice 类型互相转化的时候,得到的新数据都是原数据的拷贝,而不是原数据。类型转化和切片重组(Resliciing)不一样,切片重组后的变量仍然指向原变量,而类型转换后的变量指向原变量的拷贝。
Go 语言已经对 []byte 和 String 类型的互相转化做了优化,并且还会继续优化。
The first optimization avoids extra allocations when []byte keys are used to lookup entries in map[string] collections: m[string(key)].
一个优化是
The second optimization avoids extra allocations in for range clauses where strings are converted to []byte: for i,v := range []byte(str) {…}.
String 与下标
级别:新手入门级
和其他语言不同,String 的下表返回值是 Byte 类型的值,而不是字符类型。
|
|
如果需要在 UTF8 类型的 String 中取出指定字符,那么需要用到 unicode/utf8 与实验性的 [utf8string]() 包。utf8string 包包含 AT() 方法,可以取出字符,也可以将 String 转换为 Rune SLice。
String并不一定是UTF8格式
级别:新手入门级
String 类型不一定是 UTF8 格式,String 中也可以包含自定义的文字/字节。只有需要将字符串显示出来的时候才需要用 UTF8 格式,其他情况下可以随便用转义来表示任意字符。
可以使用 unicode/utf8 包中体重的 ValidString() 方法判断是否是 UTF8 类型的文本。
|
|
String 长度
级别:新手入门级
Python 开发者的代码:
|
|
转换成类似的 Go 代码如下:
|
|
Go 的 len() 方法和 Python 的并不相同,和 Python 的 len 方法等价的 Go 方法是 RuneCountInString。
|
|
当然有些情况(例如法语)的情况,RuneCountInString 也并不能完全返回字符数目,因为有些字符是使用多个字符的方式进行存储的。
|
|
多行的 Slice Arry 和 Map 赋值中缺少逗号
Missing Comma In Multi-Line Slice, Array, and Map Literals
级别:新手入门级
错误信息:
|
|
Compile Errors:
|
|
修正代码:
|
|
当然,如果把这些东西写在一行中,可以不加最后的逗号。
log.Fatal 与 log.Panic 在后台悄悄做了一些事情
级别:新手入门级
日志库提供了不同级别的日志记录,如果使用 Fatal 和 Panic 级别的日志,那么记录完这条日志后,应用程序便会退出而不会继续执行。
|
|
内置的数据结构操作是无锁的
级别:新手入门级
虽然 Go 语言天生高并发,但是 Go 并没有考虑到数据安全。为了实现“原子化”的数据操作,开发者需要自己对数据操作进行加锁。当然, goroutine 和 channel 以及 sync 都是手动加锁的好方案。