登录
首页 >  Golang >  Go问答

为何地图上找不到钥匙

来源:stackoverflow

时间:2024-03-10 20:09:26 322浏览 收藏

学习Golang要努力,但是不要急!今天的这篇文章《为何地图上找不到钥匙》将会介绍到等等知识点,如果你想深入学习Golang,可以关注我!我会持续更新相关文章的,希望对大家都能有所帮助!

问题内容

我创建了一张地图:

l := make(map[*a]string)

其中 a 是:

type a struct{}

然后向其中添加键值:

a1 := &a{}
a2 := &a{}
a3 := &a{}

l[a1] = "a1"
l[a2] = "a2"
l[a3] = "a3"

我希望在执行 range 时看到所有值(“a1”、“a2”、“a3”)

for k, v := range l{
    fmt.Println(k, v)
}

但我只看到最后一个。

为什么会发生这种情况? https://play.golang.org/p/gsduwzexxlk


解决方案


因为你的结构体没有字段,go 会将所有指向它的指针优化为相同的地址,因此你每次都使用相同的键。为该结构体提供一个字段(即使您从未在其中输入值),您将获得预期的行为。

演示:https://play.golang.org/p/n-WUZ9wqpGJ

您可以阅读有关空结构(包括此指针行为)的更多信息 on Dave Cheney's blog

它在规范中仅在 Sizes and Alignments 下简单提及,实际上是规范中的最后一句话:

如果结构体或数组类型不包含大小大于零的字段(或元素),则其大小为零。两个不同的零大小变量在内存中可能具有相同的地址。

这是因为 a 是一个空结构。由于它无法更改,所以 go 总是为其分配相同的内存地址。如果您向 a 添加字段,它将开始工作:

type a struct{a string}

func main() {
    a1 := a{}
    a2 := a{}

    l := make(map[*a]string)
    l[&a1] = "a1"
    l[&a2] = "a2"

    for i, v := range l{
        i := i
        fmt.println(&i, v)
    }
}

打印:

0x40e138 a1
0x40e150 a2

https://play.golang.org/p/hYzU73kbVPV

戴夫·切尼在这里进行了更深入的探讨:

https://dave.cheney.net/2014/03/25/the-empty-struct

本篇关于《为何地图上找不到钥匙》的介绍就到此结束啦,但是学无止境,想要了解学习更多关于Golang的相关知识,请关注golang学习网公众号!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>