1. 背景
上周四小伙伴发了Go社区一个帖子下hej8875的回复,如下:
package main import "fmt" func main() { s := []byte("") s1 := append(s, 'a') s2 := append(s, 'b') //fmt.Println(s1, "==========", s2) fmt.Println(string(s1), "==========", string(s2)) } // 出现个让我理解不了的现象, 注释时候输出是 b ========== b // 取消注释输出是 [97] ========== [98] a ========== b
这个回复比原贴有意思,也很有迷惑性。作者测试了下,确实如此,于是和小伙伴们讨论深究下。开始以为应该挺简单的,理解后,发现涉及挺多知识点,值得跟大家分享下过程。
2. slice
2.1 内部结构
先抛去注释的这行代码//fmt.Println(s1, "==========", s2)
,后面在讲。 当输出 b ========== b
时,已经不符合预期结果a和b了。我们知道slice内部并不会存储真实的值,而是对数组片段的引用,其内部结构是:
type slice struct { data uintptr len int cap int }
其中data是指向数组元素的指针,len是指slice要引用数组中的元素数量。cap是指要引用数组中(从data指向开始计算)剩余的元素数量,这个数量减去len,就是还能向这个slice(数组)添加多少元素,如果超出就会发生数据的复制。slice的示意图:
s := make([]byte, 5)// 下图
s = s[2:4] //会重新生成新的slice,并赋值给s。与底层数组的引用也发生了改变
2.2 覆盖前值
回到问题上,由此可以推断出:s := []byte("")
这行代码中的s实际引用了一个 byte 的数组。
其capacity 是32,length是 0:
s := []byte("
nge
cui***nge1995@gmail.com
寻找到 100 以内的所有的素数: