一尘不染

将一个元素附加到零切片将容量增加两个

go

我有零片:

var s1 []int // len(s1) == 0, cap(s1) == 0

我在其中添加一个元素:

s2 := append(s1, 1) // len(s2) == 1, cap(s2) == 2

为什么在一个nil slice上附加一个元素会使容量增加2?

使用来打印切片fmt.Printf显示以下内容:

[] // s1
[1] // s2

我也很困惑为什么重新切片会s2[0:2]显示一个零,该零既不在原始切片中也不附加在原始切片上:

[1,0] // s2[0:2]

阅读 215

收藏
2020-07-02

共1个答案

一尘不染

Go可以免费为您提供超出您要求的容量。通过减少所需的分配(可以复制)数量来提高性能。容量只是在需要另一分配之前保留的空间量。

如果至少在我的实验中将5个元素添加到此片中,则容量为8。这并不奇怪,但也不应依赖。在不同平台或不同版本的编译器上,只要容量“足够大”(等于或大于长度),实际结果就可能不同。

切片的上索引上限定义为其容量

对于数组或字符串,如果0 <=低<=高<=
len(a),则索引在范围内,否则它们超出范围。对于切片,索引的上限是切片容量cap(a)而不是长度。常数索引必须是非负数,并且可以由int类型的值表示;对于数组或常量字符串,常量索引也必须在范围内。如果两个索引都恒定,则它们必须满足低<=高。如果索引在运行时超出范围,则会发生运行时恐慌。

这就是为什么阅读超过长度不会引起恐慌的原因。即使这样,您也不应将这些零视为切片的一部分。它们可通过切片索引,但fmt.Printf(s2)由于它们不属于切片,因此无法正确显示它们。不要这样下标。

通常,您要查看的是长度而不是容量。大部分容量都是可读的,以帮助优化性能。

2020-07-02