之前也翻译过两篇 Dave 大神的文章,可以看这里《 》和《 》,很多人问他是谁?给大家简单介绍下:
他是 Go 语言的开源贡献者和项目成员,技术界中受人尊敬的代言人,在软件设计、性能和 Go 语言等各种主题上发表演讲。在油管上可以看到很多他演讲的视频,反正就是很牛逼!
博客地址:
原文如下:
在上一篇文章中,给大家说明了 Go 语言的 map 不是引用变量,也不会通过引用传递。这留了一个问题,如果 map 不是引用变量,那它们是什么?
不急,先看答案:
map 是指向 runtime .hmap 结构体的指针。
如果你不满意这种解释,接着往下看。
map 值的类型是什么?
当你写下如下代码
编译器会自动去调用 runtime.makemap,看下方法签名:
正如你看到的那样,从 runtime.makemap 返回的值的类型是指向 runtime.hmap 结构体的指针。从平常的代码中看不出这一点,但我们可以确认的是 map 值的大小与 uintptr 相同。
如果 map 是指针,那是不是应该这样表示 *map[key]value ?
这是个好问题,如果 map 是指针的话,为什么表达式 make(map[int]int) 返回的是类型为 map[int]int 的值,不是应该返回 *map[int]int 吗?
可以说,将类型从 *map[int]int 重命名为 map[int]int 虽然有点混乱,因为类型看起来不像指针,但相较于指针值不能解引用,混乱程度会好点。
总结
map 与 channel 一样,都是 runtime 类型的指针, 这与 slice 不同。正如你在上面看到的那样,map 是指向 runtime.hmap 结构体的指针。
map 与 Go 语言中其他类型的指针值具有相同的指针语义,除了编译器会将 map 重写为对 runtime/map.go 函数的调用外,并没有什么任何特殊之处。