在学习切片时,我有这样的疑问:append()是否总是扩展所需的最小容量?
a := make([]byte, 0)
a = append(a, 1, 2, 3)
cap(a) == 3 // will this be always true?
// or the assumption may not hold since the underlying implementation of append()
// is not specified.
答案 0 :(得分:3)
不,在这种情况下无法保证。 specifications说:
append(s S, x ...T) S // T is the element type of S
如果s的容量不足以容纳附加值,则append会分配一个新的足够大的切片,该切片适合现有切片元素和其他值。因此,返回的切片可以引用不同的底层数组。
(强调我的)
在您的情况下,显然任何容量> = 3 足够大,因此可以依赖 cap >= 3
,但你不能< / em>依赖cap == 3
。
当然,你可以假设在这种情况下的上限不会是1e6或1e9或1e12。但是,有意识地没有在每个细节中指定确切的扩大(分配新的后备阵列)策略,以允许编译器人员尝试附加到该机制的一些旋钮。
答案 1 :(得分:2)
我想补充一点,它不仅不保证切片的容量等于长度,事实上,对于大长度,它几乎不会是生成的切片具有容量等于长度的情况。
append()
被提升为vector
包的替代品。为了做到这一点,附加的复杂性必须与vector
包中的复杂性相匹配,这意味着附加元素必须具有分摊的O(1)复杂度。虽然在语言规范中无法保证这种复杂性,但对于现在在Go社区中使用append()
的模式来说,它必须是有效的。
为了使append()
摊销O(1),它必须在每次空间不足时将容量扩展固定百分比的当前容量。例如,容量翻倍。想一想,如果每次耗尽时容量增加一倍,如果长度恰好是2的幂(假设它的最小值为2),则长度和容量只能相同,这不常见。