Go陷阱|第1章: append
Synopsis: 使用内置函数 append() 在切片末尾追加元素并返回新切片时,要注意是否会创建新的底层数组
1. 问题现象
package main import "fmt" func main() { s := []byte("ca") fmt.Printf("%v len=%d cap=%d\n", s, len(s), cap(s)) // [99 97] len=2 cap=2 s1 := append(s, 'r') s2 := append(s, 't') fmt.Println(string(s1)) fmt.Printf("%v len=%d cap=%d\n", s1, len(s1), cap(s1)) fmt.Println(string(s2)) fmt.Printf("%v len=%d cap=%d\n", s2, len(s2), cap(s2)) }
用我的电脑上的 cmd 执行输出结果正常:
但是,用 Golang Playground 执行输出结果不正常:
2. 原因分析
如果切片引用的底层数组还有足够的可用容量时,用 append()
函数不会创建新的底层数组
在无需扩容时,append() 函数返回的是指向原底层数组的新切片;而在需要扩容时,append() 函数返回的是指向新底层数组的新切片。只要新长度不会超过当前切片的原容量,那么使用 append() 函数对其追加元素时就不会引起扩容,这只会使紧邻切片窗口右边的(原底层数组中的)元素被新的元素替换掉!
给类型分配多少内存与编译代码的机器的体系结构有关。例如,根据编译所在的机器的体系结构,一个 int 值的大小可能是 8 字节(64 位),也可能是 4 字节(32 位)
由于我的电脑给切片 []byte("ca")
所引用的底层数组分配了 2 个字节(它的容量为 2),所以 s1 和 s2 使用 append()
函数时都会各自创建一个新的底层数组;而 Playground 给切片 []byte("ca")
所引用的底层数组分配了 8 个字节(它的容量为 8),所以 s1 和 s2 使用 append()
函数时还是引用原来的同一个底层数组
3. 解决方案
s1 和 s2 分别对不同的切片(不同的底层数组)进行 append
0 条评论
评论者的用户名
评论时间暂时还没有评论.