Go中的切片容量

时间:2016-07-25 17:26:28

标签: go append 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)
}       

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

结果:
在我的本地游览服务器上:

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]      

在最后一行之前一切都好,但我没有得到

cap=6     

为什么不

cap=5    

我的意见是我没有创建具有显式容量的切片,因此我的系统给了它 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]   

第二行上限= 2 ,最后一行上限= 8 怎么样?

1 个答案:

答案 0 :(得分:12)

这个问题并不完全重复,但我的回答here也有效地回答了这个问题。

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

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