关于切片的append()行为感到困惑。

huangapple go评论83阅读模式
英文:

Confused about append() behavior on slices

问题

主要原因是在进行切片操作时,如果切片的容量足够,那么在追加元素时,底层数组不会发生改变。因此,当你追加元素到slice1时,如果底层数组的容量足够,sliceslice1仍然指向同一个底层数组,因此对slice1的修改也会反映在slice上。

然而,如果在追加元素时,底层数组的容量不足,那么会创建一个新的底层数组,并将原有的元素复制到新的数组中。这时,slice1slice将指向不同的底层数组,对slice1的修改不会影响到slice

在你的代码中,切片slice的容量为10,当你追加元素到slice1时,底层数组的容量仍然足够,因此sliceslice1指向同一个底层数组,对slice1的修改也会影响到slice

英文:
func main() {
    slice := make([]int, 10, 10)
    slice[0] = 0
    slice[1] = 1

    slice1 := slice
    slice1[0] = 10000
    fmt.Println(slice)

    slice1 = append(slice1, 100)
    slice1[0] = 20000

    fmt.Println(slice)
}

result:
> [10000 1 0 0 0 0 0 0 0 0]
>
> [10000 1 0 0 0 0 0 0 0 0]

In my understanding, slice is a pointer, slice1 and slice point to the same array, and the first output also proves this. But why did slice's value remain unchanged after the append operation changed slice1?

答案1

得分: 8

append() 函数不会改变 slice1,因为在 Go 语言中,所有的东西都是按值传递的,所以它只接收到一个副本。由于最初你创建的 slice 的容量等于其长度(make([]int, 10, 10)),任何添加超过 0 个元素的操作都需要分配一个新的、更大的数组。这就是你的 append() 调用所做的。它会复制旧数组的内容,并返回一个指向新数组的切片值(切片头部)。然后你将返回值赋给了 slice1,这个赋值是改变了 slice1 的原因。

slice1 的任何赋值都不会改变 slice 的值,它们是两个不同的变量,两个不同的切片头部。因此,添加的元素在 slice 中是不可见的。而且由于 append() 必须创建一个新的数组,对 slice1slice 的元素所做的更改也不会再相互反映。

要查看切片头部的内容,请参阅 https://stackoverflow.com/questions/39993688/are-golang-slices-pass-by-value/39993797#39993797

要了解更多关于切片的信息,请阅读博文 Go Slices: usage and internals

英文:

The append() didn't change slice1; it can't as everything in Go is passed by value, so it only receives a copy of it. Since initially you created the slice with capacity equal to its length (make([]int, 10, 10)), any append operation with more than 0 elements requires allocation of a new, bigger array. This is what your append() call does. And it copies over the contents of the old array, and returns a slice value (slice header) pointing to the new array. And you assign the return value to slice1, and this assignment is what changes slice1.

Any assignment to slice1 does not change the value of slice, they are 2 distinct variables, 2 distinct slice headers. So the appended elements will not be visible in slice. And since the append() had to create a new array, changes made to the elements of slice1 and slice will also not be reflected in one another anymore.

To see what's inside a slice header, see https://stackoverflow.com/questions/39993688/are-golang-slices-pass-by-value/39993797#39993797

To learn more about slices, read blog post Go Slices: usage and internals.

答案2

得分: 2

因为 append 可以决定返回底层数组的一个完全新的副本。

英文:

Because an append can decide to return an entirely new copy of the underlying array.

huangapple
  • 本文由 发表于 2017年9月7日 15:37:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/46090572.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定