英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论