go-map原理解析
| 阅读 | 共 573 字,阅读约
Overview
map原理
- map数据结构
- map初始化
- 插入
- 删除
- 扩容
- 遍历
- NAN
结构体
源码位置:src/runtime/map.go
1type hmap struct {
2 // 元素数量
3 count int
4 // 标识目前map的状态:写、扩容
5 flags uint8
6 // log_2 桶数量
7 B uint8
8 // 元素超出该数量认为溢出
9 noverflow uint16
10 hash0 uint32 // hash seed
11 // 桶数组,指向bmap,长度为 2^B
12 buckets unsafe.Pointer
13 // 扩容用的桶
14 oldbuckets unsafe.Pointer
15 // 扩容进度
16 nevacuate uintptr
17 // 可选字段,额外属性
18 extra *mapextra // optional fields
19}
20
21// 桶
22type bmap struct {
23 // 不仅仅只有这个字段,其他字段是在编译时加进去的,因为map中存放的数据类型不确定
24 // 参考 src/cmd/compile/internal/gc/reflect.go的bmap函数
25
26 // bucketCnt=8,也就是bmap中的桶固定只有8个格子,每个格子内存放一对key-value,
27 // 表示key-value的字段并不在这里表示,而是编译时动态添加的
28 tophash [bucketCnt]uint8
29
30 // 其他编译生成的字段包括
31 // overflow 用于连接下一个bmap(溢出桶)
32}
map初始化
1func makemap(t *maptype, hint int, h *hmap) *hmap {
2 mem, overflow := math.MulUintptr(uintptr(hint), t.bucket.size)
3 if overflow || mem > maxAlloc {
4 hint = 0
5 }
6
7 // initialize Hmap
8 if h == nil {
9 h = new(hmap)
10 }
11 h.hash0 = fastrand()
12
13 // Find the size parameter B which will hold the requested # of elements.
14 // For hint < 0 overLoadFactor returns false since hint < bucketCnt.
15 B := uint8(0)
16 for overLoadFactor(hint, B) {
17 B++
18 }
19 h.B = B
20
21 // allocate initial hash table
22 // if B == 0, the buckets field is allocated lazily later (in mapassign)
23 // If hint is large zeroing this memory could take a while.
24 if h.B != 0 {
25 var nextOverflow *bmap
26 h.buckets, nextOverflow = makeBucketArray(t, h.B, nil)
27 if nextOverflow != nil {
28 h.extra = new(mapextra)
29 h.extra.nextOverflow = nextOverflow
30 }
31 }
32
33 return h
34}