-2

我遇到了这个简单的 Golang 代码,并对 Go 在这里的行为感到惊讶。有人可以解释这里发生了什么,以及如何正确编写下面的代码吗?

如您所见,我有一个map,其中键是arrayof int。我添加了几个值,然后循环遍历map,将每个键转换为 aslice并将每个键附加到类型的对象[][]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)
}

我期待最后一行 print [[1,2,3], [0,5,4], [9,7,1], [0,2,8]],然而,令我惊讶的是,它会多次打印[[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]]

我的 go 版本是1.16.5

4

3 回答 3

2

在 for 循环中,循环变量在每次迭代时都会被覆盖。也就是说,val是一个数组,并且对于每次迭代, 的内容都会val被映射中的下一项覆盖。由于您添加了切片(它们只是数组上的视图),所有切片都val作为支持数组,并且它们都具有相同的内容,即,无论最后一个元素迭代。

要修复,请复制数组:

    for val := range myMap {
        val:=val
        array = append(array, val[:])
    }
于 2021-07-12T16:57:05.600 回答
2

您每次都附加循环迭代器变量,每次迭代都会更新。您需要附加一个本地范围的副本:

for val := range myMap {
    v := val
    array = append(array, v[:])
}
于 2021-07-12T16:57:10.560 回答
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]]
于 2021-07-12T18:44:18.303 回答