英文:
Confused about append() behavior on slices
问题
主要原因是在进行切片操作时,如果切片的容量足够,那么在追加元素时,底层数组不会发生改变。因此,当你追加元素到slice1时,如果底层数组的容量足够,slice和slice1仍然指向同一个底层数组,因此对slice1的修改也会反映在slice上。
然而,如果在追加元素时,底层数组的容量不足,那么会创建一个新的底层数组,并将原有的元素复制到新的数组中。这时,slice1和slice将指向不同的底层数组,对slice1的修改不会影响到slice。
在你的代码中,切片slice的容量为10,当你追加元素到slice1时,底层数组的容量仍然足够,因此slice和slice1指向同一个底层数组,对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() 必须创建一个新的数组,对 slice1 和 slice 的元素所做的更改也不会再相互反映。
要查看切片头部的内容,请参阅 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论