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
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[:])
}