本想写一篇关于 golang 中 map 底层的文章, 但是发现已经了相当不错的文章 –
字节跳动技术团队 - Golang 中 map 探究
这里只补充一下,缺少的 map 的删除操作
内部数据结构#
初始化#
map 是一个有"包含内容"的数据结构, 使用之前需要提前初始化, 即调用make
真正是调用源码是 runtime.makemap
获取数据#
源码地址
删除的关键代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
// Only clear key if there are pointers in it.
// # 当 Key 是指针类型的时候会去清空指针
if t.key.ptrdata != 0 {
if goarch.PtrSize == 8 {
*(*unsafe.Pointer)(k) = nil
} else {
// There are three ways to squeeze at one ore more 32 bit pointers into 64 bits.
// Just call memclrHasPointers instead of trying to handle all cases here.
memclrHasPointers(k, 8)
}
}
e := add(unsafe.Pointer(b), dataOffset+bucketCnt*8+i*uintptr(t.elemsize))
// # 当 Value 为指针类型的时候, 指针为空, 解除引用 -> GC
if t.elem.ptrdata != 0 {
memclrHasPointers(e, t.elem.size)
} else {
memclrNoHeapPointers(e, t.elem.size)
}
// # 讲 hash 值标记为空
b.tophash[i] = emptyOne
|
上述删除代码操作现象
- 当
map
的value
类型中包含引用类型, 删除对应的key
之后, 经过GC就会释放占用的内存 - 当
map
的value
类型不包含引用类型, 删除对应的key
之后, GC无法释放类型
可以查看我自己的实验结果 {{}}
https://ynikl.github.io/blog/golang-memory-analyze-with-runtime/
Golang 中 map 探究