Capacity of slices in Go
我有一个关于下面代码的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | package main import"fmt" func main() { var a []int printSlice("a", a) // append works on nil slices. a = append(a, 0) printSlice("a", a) // the slice grows as needed. a = append(a, 1) printSlice("a", a) // we can add more than one element at a time. a = append(a, 2, 3, 4) printSlice("a", a) } func printSlice(s string, x []int) { fmt.Printf("%s len=%d cap=%d %v ", s, len(x), cap(x), x) } |
我总是猜测运行一段代码的结果会是什么样子,然后运行代码并检查我的猜测是否正确。但这段代码与我的猜测有点不同:
结果:在本地Go Tour服务器上:
1 2 3 4 | a len=0 cap=0 [] a len=1 cap=1 [0] a len=2 cap=2 [0 1] a len=5 cap=6 [0 1 2 3 4] |
号
到最后一行一切都好,但我不知道
1 | cap=6 |
为什么不
1 | cap=5 |
。
我的观点是,我没有用显式的能力创建slice,因此我的系统给它6的值。
2)但是当我在Golang Tour服务器上尝试相同的代码时,我得到了一个更为不同的结果,比如:
1 2 3 4 | a len=0 cap=0 [] a len=1 cap=2 [0] a len=2 cap=2 [0 1] a len=5 cap=8 [0 1 2 3 4] |
第二行的cap=2,最后一行的cap=8怎么样?
这个问题不完全重复,但我在这里的回答也有效地回答了这个问题。
tl;dr-规范中没有提到片的扩展容量,go的不同版本(或不同的实现,或不同体系结构上的相同版本等)可以将片扩展不同的数量。
您可能希望使容量大于所需容量的原因是,在切片下面有一个不可变的数组(它不能扩展)。当您"增长"一个切片时,实际发生的是您创建一个新的(更长的)数组,复制所有值,然后将其设置为切片的后备数组。如果您要附加大量的值,则必须进行大量的复制(每个值一个),这将非常缓慢,因此运行时分配的空间比您认为需要的要大,因此它必须减少复制的频率。