Go中的切片容量

Mak*_*bov 9 append go slice

我对以下代码有疑问

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\n",
    s, len(x), cap(x), x)
}       
Run Code Online (Sandbox Code Playgroud)

我总是猜测运行一段代码的结果会是什么样子然后运行代码并检查我的猜测是否正确.但是这个代码与我的猜测有点不同:

结果:
在我当地的旅游服务器上:

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]      
Run Code Online (Sandbox Code Playgroud)

一切都好,直到最后一行,但我没有

cap=6     
Run Code Online (Sandbox Code Playgroud)

为什么不

cap=5    
Run Code Online (Sandbox Code Playgroud)

我的意见是我没有创建具有显式容量的切片,因此我的系统给它的值为6.

2)但是当我在golang tour服务器上尝试这个相同的代码时,我会得到更多不同的结果,如下所示:

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]   
Run Code Online (Sandbox Code Playgroud)

那么第二行的cap = 2和最后一行的cap = 8怎么样?

Sam*_*ted 12

这个问题不是一个确切的重复,但我的答案在这里也有效地回答了这个.

TL; DR - 规范中未提及切片容量扩展的程度,Go的不同版本(或不同的实现,或不同体系结构上的相同版本等)可以按不同的数量扩展切片.

您可能希望使容量大于您需要的原因是因为在切片下面有一个不可变的数组(它不能展开).当您"增长"切片时,实际发生的是您创建一个新的(更长的)数组,复制所有值,然后将其设置为切片的支持数组.如果要附加大量值,则必须执行大量复制(每个值一个),这将非常慢,因此运行时会分配比您认为需要的更多空间,以便它必须减少复制次数.