英文:
Golang: Appending keys from a map to a slice of slices
问题
我遇到了这段简单的 Golang 代码,对 Go 的行为感到惊讶。有人能解释一下这里发生了什么,并且如何正确编写下面的代码吗?
如你所见,我有一个 map
,其中键是一个 int
数组。我添加了一些值,然后遍历该 map
,将每个键转换为一个 slice
,并将每个键附加到类型为 [][]int
的对象中。
func test() {
myMap := make(map[[3]int]bool)
myMap[[3]int{1, 2, 3}] = true
myMap[[3]int{0, 5, 4}] = true
myMap[[3]int{9, 7, 1}] = true
myMap[[3]int{0, 2, 8}] = true
array := [][]int{}
for val := range myMap {
array = append(array, val[:])
}
fmt.Println(array)
}
我原本期望最后一行打印 [[1,2,3], [0,5,4], [9,7,1], [0,2,8]]
,然而,令我惊讶的是它打印出了 [[0 2 8] [0 2 8] [0 2 8] [0 2 8]]
,或者 [[9 7 1] [9 7 1] [9 7 1] [9 7 1]]
,或者其他只包含一个键多次的变体。
我的 Go 版本是 1.16.5
。
英文:
I ran into this simple Golang code and was surprised by Go's behavior here. Can someone explain what is going on here, and how to write the below code correctly?
As you can see, I have a map
, where the key is an array
of int
. I add a couple of values and then I loop through the map
, convert each key to a slice
and append each key to an object of type [][]int
.
func test() {
myMap := make(map[[3]int]bool)
myMap[[3]int{1, 2, 3}] = true
myMap[[3]int{0, 5, 4}] = true
myMap[[3]int{9, 7, 1}] = true
myMap[[3]int{0, 2, 8}] = true
array := [][]int{}
for val := range myMap {
array = append(array, val[:])
}
fmt.Println(array)
}
I was expecting the last line to print [[1,2,3], [0,5,4], [9,7,1], [0,2,8]]
, however, to my surprise it prints [[0 2 8] [0 2 8] [0 2 8] [0 2 8]]
, or [[9 7 1] [9 7 1] [9 7 1] [9 7 1]]
, or some other variation containing only one of the keys multiple times.
My go version is 1.16.5
答案1
得分: 4
在for循环中,循环变量在每次迭代时被覆盖。也就是说,val
是一个数组,每次迭代时,val
的内容都会被下一个映射项覆盖。由于你添加了切片(切片只是数组的视图),所有的切片都以val
作为支持数组,并且它们都具有相同的内容,即最后一个迭代的元素。
要修复这个问题,需要复制数组:
for val := range myMap {
val := val
array = append(array, val[:])
}
英文:
In a for-loop, the loop variables are overwriten at every iteration. That is, the val
is an array, and for each iteration, the contents of val
are overwritten with the next item in the map. Since you added slices (which are simply views over an array), all the slices have val
as the backing array, and they all have the same contents, namely, whatever the last element iterated.
To fix, copy the array:
for val := range myMap {
val:=val
array = append(array, val[:])
}
答案2
得分: 3
你每次都在追加循环迭代变量,该变量在每次迭代时更新。你需要追加一个局部作用域的副本:
for val := range myMap {
v := val
array = append(array, v[:])
}
英文:
You're appending the loop iterator variable each time, which is updated each iteration. You need to append a locally-scoped copy instead:
for val := range myMap {
v := val
array = append(array, v[:])
}
答案3
得分: 1
根据Adrian的建议,使用以下简单程序重新创建你的代码:
package main
import (
"fmt"
)
func main() {
test()
}
func test() {
myMap := make(map[[3]int]bool)
myMap[[3]int{1, 2, 3}] = true
myMap[[3]int{0, 5, 4}] = true
myMap[[3]int{9, 7, 1}] = true
myMap[[3]int{0, 2, 8}] = true
array := [][]int{}
for val := range myMap {
key := val
array = append(array, key[:])
}
fmt.Println(array)
}
输出结果:
[[1 2 3] [0 5 4] [9 7 1] [0 2 8]]
英文:
Based on suggestion of Adrian, recreating your code with a simple program as follows:
package main
import (
"fmt"
)
func main() {
test()
}
func test() {
myMap := make(map[[3]int]bool)
myMap[[3]int{1, 2, 3}] = true
myMap[[3]int{0, 5, 4}] = true
myMap[[3]int{9, 7, 1}] = true
myMap[[3]int{0, 2, 8}] = true
array := [][]int{}
for val := range myMap {
key := val
array = append(array, key[:])
}
fmt.Println(array)
}
Output:
[[1 2 3] [0 5 4] [9 7 1] [0 2 8]]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论