Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
追加时Go切片容量如何变化?_Go_Slice - Fatal编程技术网

追加时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] 本地计算机上的输出如

在服务器上运行这个示例(当前版本为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=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()行为是不同的@尤金尼奥的回答是正确的。