追加时Go切片容量如何变化?
在服务器上运行这个示例(当前版本为1.12.7),我发现如果新的片长度大于当前备份阵列的长度,片的容量将加倍到下一个2的幂次方 如果我在我的机器上运行相同的程序(windows上的版本1.10.3),片容量将更改为两个的下一个倍数 为什么它们不同?这是因为Go版本还是运行时实现?容量变化是否具有确定性 远程服务器上的输出如下所示追加时Go切片容量如何变化?,go,slice,Go,Slice,在服务器上运行这个示例(当前版本为1.12.7),我发现如果新的片长度大于当前备份阵列的长度,片的容量将加倍到下一个2的幂次方 如果我在我的机器上运行相同的程序(windows上的版本1.10.3),片容量将更改为两个的下一个倍数 为什么它们不同?这是因为Go版本还是运行时实现?容量变化是否具有确定性 远程服务器上的输出如下所示 len=0 cap=0 [] len=1 cap=2 [0] len=2 cap=2 [0 1] len=5 cap=8 [0 1 2 3 4] 本地计算机上的输出如
len=0 cap=0 []
len=1 cap=2 [0]
len=2 cap=2 [0 1]
len=5 cap=8 [0 1 2 3 4]
本地计算机上的输出如下所示
len=0 cap=0 []
len=1 cap=1 [0]
len=2 cap=2 [0 1]
len=5 cap=6 [0 1 2 3 4]
这是供参考的代码
package main
import "fmt"
func main() {
var s []int
printSlice(s)
// append works on nil slices.
s = append(s, 0)
printSlice(s)
// The slice grows as needed.
s = append(s, 1)
printSlice(s)
// We can add more than one element at a time.
s = append(s, 2, 3, 4)
printSlice(s)
}
func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
根据append实现的信息,其行为如下 它只是
(len(源片)+len(新数据))*2的倍数
func AppendByte(slice []byte, data ...byte) []byte {
m := len(slice)
n := m + len(data)
if n > cap(slice) { // if necessary, reallocate
// allocate double what's needed, for future growth.
newSlice := make([]byte, (n+1)*2)
copy(newSlice, slice)
slice = newSlice
}
slice = slice[0:n]
copy(slice[m:n], data)
return slice
}
TL;DR:这取决于数组中存储的元素的大小
可以在此处看到实现:
但是,正如你所看到的那样,纵观历史,不能指望随着时间的推移保持不变
这也可能解释了不同版本的围棋之间的差异
做一些测试来说明一个0大小的结构如何只增加1个元素的容量,int或string在每次增长时都会重复,而一个3字节的结构在每次增长时“大致”翻一番
您可以使用不同的类型执行类似的代码,以查看这些不同的情况:
arr := []struct{}{}
oldCap := 0
for i := 0; i < 100; i++ {
arr = append(arr, struct{}{})
if cap(arr) != oldCap {
oldCap = cap(arr)
fmt.Println("arr", cap(arr))
}
}
arr:=[]结构{}{}
oldCap:=0
对于i:=0;i<100;i++{
arr=append(arr,结构{}{})
如果cap(arr)!=旧cap{
oldCap=cap(arr)
fmt.Println(“arr”,cap(arr))
}
}
展示上述案例的游乐场:
在这两种情况下,您能否共享输出容量。具体实现如下。应用程序不应该依赖于如何增加容量。不,它只是自我实现的“append()”函数的一个示例。当您不想依赖内部Go实现时,可以使用它。但是内置的append()行为是不同的@尤金尼奥的回答是正确的。