【问题标题】:Golang: Appending keys from a map to a slice of slicesGolang:将地图中的键附加到切片中
【发布时间】:2021-09-21 20:15:09
【问题描述】:

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

如您所见,我有一个map,其中的键是int 的array。我添加了几个值,然后循环遍历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

【问题讨论】:

    标签: go slice go-map


    【解决方案1】:

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

    要修复,复制数组:

        for val := range myMap {
            val:=val
            array = append(array, val[:])
        }
    

    【讨论】:

      【解决方案2】:

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

      for val := range myMap {
          v := val
          array = append(array, v[:])
      }
      

      【讨论】:

        【解决方案3】:

        根据 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]]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-12-10
          • 2016-05-25
          • 2019-01-02
          • 2017-08-11
          • 2016-12-24
          • 2018-02-05
          • 1970-01-01
          • 2020-12-09
          相关资源
          最近更新 更多