go - 循环映射时去追加很奇怪

标签 go

我也尝试循环映射(使用数组作为键)时遇到了golang怪异的行为。您可以通过游乐场去复制它。
https://play.golang.org/p/GNVBJTpoR98

package main

import "fmt"

func main() {
    m := make(map[[2]int]bool, 0)
    m[[2]int{1, 2}] = true
    m[[2]int{1, 3}] = true

    res := make([][]int, 0)

    for ke, _ := range m {
        res = append(res, ke[:])
    }

    fmt.Println(res)    
    // expect: [[1 2] [1 3]]
    // actual: [[1 3] [1 3]]


}
这是golang的错误吗?

最佳答案

这不是错误,这是预期的行为。为循环定义了ke变量,然后在每次迭代中都保留了当前映射键的引用。将其 slice 附加到res时,将使用ke的引用,该引用在循环的末尾引用 map 的最后一个键。
解决方案是在循环内创建一个新的引用作为临时变量:

for ke, _ := range m {
    v := ke
    res = append(res, v[:])
}
有关更多详细信息,请查看官方文档(感谢@Marc提供的链接):https://github.com/golang/go/wiki/CommonMistakes#using-reference-to-loop-iterator-variable

关于go - 循环映射时去追加很奇怪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63471131/

相关文章:

string - slice 无法转换为字符串

go - 在 Go 中打开多个 keep-alive 到服务器

python - 为什么我的 Go 程序在以下场景中的性能比预期差很多?

go - SETEX 错​​误 - "Use of closed network connection"

json - 忽略 JSON Marshal 上不支持的类型错误

go - 如何与和/或在文本/模板中短路

dictionary - Golang 效率中的非泛型映射

正则表达式 "is not a constant"编译错误

go - 是否可以将 Go Task runner 配置为使用文件扩展名 yaml?

go - 如何在golang中捕获堆栈溢出错误