『就要学习 Go 语言』系列 -- 第 32 篇分享好文
之前也翻译过两篇 Dave 大神的文章,可以看这里《
他是 Go 语言的开源贡献者和项目成员,技术界中受人尊敬的代言人,在软件设计、性能和 Go 语言等各种主题上发表演讲。在油管上可以看到很多他演讲的视频,反正就是很牛逼!
博客地址:https://dave.cheney.net/
原文如下:
在
不急,先看答案:
map 是指向 runtime.hmap 结构体的指针。
如果你不满意这种解释,接着往下看。
map 值的类型是什么?
当你写下如下代码
1m := make(map[int]int)
编译器会自动去调用 runtime.makemap,看下方法签名:
1// makemap implements a Go map creation make(map[k]v, hint)
2// If the compiler has determined that the map or the first bucket
3// can be created on the stack, h and/or bucket may be non-nil.
4// If h != nil, the map can be created directly in h.
5// If bucket != nil, bucket can be used as the first bucket.
6
7func makemap(t *maptype, hint int64, h *hmap, bucket unsafe.Pointer) *hmap
正如你看到的那样,从 runtime.makemap 返回的值的类型是指向 runtime.hmap 结构体的指针。从平常的代码中看不出这一点,但我们可以确认的是 map 值的大小与 uintptr 相同。
1package main
2
3import (
4 "fmt"
5 "unsafe"
6)
7
8func main() {
9 var m map[int]int
10 var p uintptr
11 fmt.Println(unsafe.Sizeof(m), unsafe.Sizeof(p)) // 8 8 (linux/amd64)
12}
如果 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 函数的调用外,并没有什么任何特殊之处。
推荐阅读:
如果我的文章对你有所帮助,点赞、转发都是一种支持!