Golang切片的append内置函数返回值

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

Golang slice append built-in function returning value

问题

这段代码的slice2的返回值是[[1 1][1 1]]。我感到困惑,因为我期望的是[[0 0][1 1]]。我无法理解为什么返回的是[[1 1][1 1]]而不是[[0 0][1 1]]。如果有人能解释一下,我将不胜感激。谢谢。

slice := []int{0, 0}
slice2 := [][]int{}

for i := range slice {
slice[0] = i
slice1 = i
slice2 = append(slice2, slice)
}
fmt.Println(slice2)

你可以在这个链接中检查代码:
play.golang.org

英文:

The return value of slice2 of this code is [[1 1][1 1]].<br>
And that got me confuse because I was expecting [[0 0][1 1]].<br>
I can't figure it out why is returning [[1 1][1 1]] and not [[0 0][1 1]].<br>
I would appreciate if someone can explain that. Thanks.

slice := []int{0, 0}
slice2 := [][]int{}

for i := range slice {
	slice[0] = i
	slice[1] = i
	slice2 = append(slice2, slice)
}
fmt.Println(slice2)

You can check the code in this link
play.golang.org

答案1

得分: 1

当你遍历切片时,它并不会给你切片的值,而是给你索引。这个for循环等同于for i:=0; i < len(slice); i++ {}。所以当它完成迭代时,slice中的两个值都是1,并且你将其两次追加到了slice2中。

如果你想要切片的值,你需要这样做:for i, v := range slice {},这样你就可以得到索引和值。如果你不想要索引,可以用_代替i

还要注意,像这样两次追加slice会追加完全相同的切片,因为切片在堆上分配时是指针,因此它是指向切片的指针。因此,slice2[0] == slice2[1],因为它们是完全相同的切片。

英文:

When you range over the slice, it is not giving you the VALUES of the slice, it is giving you the indexes. This for loop is equivalent to for i:=0; i &lt; len(slice); i++ {}. So by the time it gets through iteration, both values are in slice are 1, and you have appended it to slice2 twice.

If you wanted the values of the slice, you would need to do for i, v := range slice {} which would give you both the indexes and the values. You could use _ in place of i if you didn't want the index.

Also note that appending slice twice like this appends the same exact slice because slices are allocated as pointers on the heap and it is therefore a pointer to the slice. Thus slice2[0] == slice2[1] because it is the same exact slice.

答案2

得分: 1

【翻译结果】:

在你的情况下,你附加的是一个切片(指针),而不是切片的值。要获得所需的结果,你需要在每次迭代中声明一个新的切片,并将新的切片附加到slice2中。

func main() {
    slice := []int{0, 0}
    slice2 := [][]int{}

    for i := range slice {
        ns := []int{0, 0}
        ns[0] = i
        ns[1] = i
        slice2 = append(slice2, ns)
    }
    fmt.Println(slice2) // 输出:[[0 0] [1 1]]
}

Playground

英文:

> A slice is a descriptor of an array segment. It consists of a pointer to the array, the length of the segment, and its capacity (the maximum length of the segment).

In your case your are appending a slice(pointer) not the slice's values. To get the desired result you have to declare a new slice in each iteration and append the new slice to slice2.

func main() {
    slice := []int{0, 0}
    slice2 := [][]int{}

    for i := range slice {
	    ns := []int{0, 0}
	    ns[0] = i
	    ns[1] = i
	    slice2 = append(slice2, ns)
    }
    fmt.Println(slice2) // Outputs: [[0 0] [1 1]]
}

Playground

答案3

得分: 0

问题在于你附加到 slice2 的是对 slice 的引用,而不是在调用时 slice 中包含的值。

这意味着最后,slice2 包含对同一切片的两个指针。对 slice 变量的任何更改都将反映在 slice2 中,反之亦然:它们指向内存中的同一位置。

作为证明,只需执行以下操作:

slice2[0][1] = 2
fmt.Println(slice2)
fmt.Println(slice)

你将得到:

[[1 2] [1 2]]
[1 2]
英文:

The problem is that what you append to slice2 is a reference to slice, not the values contained in slice at the time of the call.

This means that at the end, slice2 contains two pointers to the same slice. Any changes to the slice variable will be reflected to slice2 and vice-versa: they point to the same location in memory.

As a proof, just do:

slice2[0][1] = 2
fmt.Println(slice2)
fmt.Println(slice)

You will get:

[[1 2] [1 2]]
[1 2] 

huangapple
  • 本文由 发表于 2017年2月21日 03:00:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/42352362.html
匿名

发表评论

匿名网友

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

确定