append()如何在导致这种情况的场景后面工作?

时间:2017-06-08 23:55:43

标签: arrays go data-structures slice

我是Go的新手,试图追踪我的代码库中的错误。在这个过程中,我把问题简化为一次调用append(),但无法弄清楚为什么它的行为方式......

func main() {
    foo := []string{"a", "b", "c"}
    fmt.Printf("before: %v\n", foo)

    i := 0
    noop(append(foo[:i], foo[i+1:]...)) // -- call append, but do nothing with the result
    fmt.Printf(" after: %v\n", foo)
}

func noop(a interface{}) {} // -- avoid "evaluated but not used" errors

Try it here

那么,这到底是怎么回事?

3 个答案:

答案 0 :(得分:5)

append(foo[:i], foo[i+1:]...)执行以下操作:

  1. foo[:i]切片为foo[:0],基本上是一个长度为0且容量(至少)为3的切片。

  2. 只要容量足以附加值 - 基础数组就会被重用

  3. 您将bc写入与基础数组相对应的索引01

  4. 然后检查使用我们刚修改的基础数组的foo变量,其中包含b c c值。

    与以下内容比较:

    noop(append(foo[:i], "a", "a", "a", "a", "a"))
    

    此处要追加的值列表长于当前容量。所以运行时分配一个新的底层数组。而且你不会改变foohttps://play.golang.org/p/RooYG_p9Z8

答案 1 :(得分:3)

  

如果s的容量不足以容纳其他值,append会分配一个足够大的新基础数组,该数组既适合现有切片元素又符合其他值。否则,append将重新使用基础数组。

分解,s此处为foo[:0],其容量至少为3,因为foo的长度为3. s有0个元素,和append想要添加两个元素[b c],因此有空间,append将重用foo[:0]的基础数组,它与{{1}的基础数组相同}}

因此它将项foo放在数组的开头,并返回长度为2的该数组的新切片。

但你还在看[b c],它是同一个数组的一部分,但长度仍为3;第三项是未被触及的foo,因此c现在为foo

答案 2 :(得分:1)

我也比较新,但我理解append的方式是它将所有以下参数附加到第一个参数。

基本上你正在做的是将foo[1]foo[2]追加到foo[0]foo[1]而不实际更改foo的长度。

如果您想保留原始切片,您需要的是this