码农桃花源
GitHub
知乎
掘金
博客园
Search…
码农桃花源
README
channel
map
map 的底层实现原理是什么
可以边遍历边删除吗
map 的删除过程是怎样的
可以对 map 的元素取地址吗
如何比较两个 map 相等
如何实现两种 get 操作
map 是线程安全的吗
map 的遍历过程是怎样的
map 中的 key 为什么是无序的
float 类型可以作为 map 的 key 吗
map 的赋值过程是怎样的
map 的扩容过程是怎样的
interface
标准库
goroutine 调度器
编译和链接
反射
数组和切片
GC
Powered By
GitBook
map 的删除过程是怎样的
写操作底层的执行函数是
mapdelete
:
1
func
mapdelete
(
t
*
maptype
,
h
*
hmap
,
key unsafe
.
Pointer
)
Copied!
根据 key 类型的不同,删除操作会被优化成更具体的函数:
key 类型
删除
uint32
mapdelete_fast32(t
maptype, h
hmap, key uint32)
uint64
mapdelete_fast64(t
maptype, h
hmap, key uint64)
string
mapdelete_faststr(t
maptype, h
hmap, ky string)
当然,我们只关心
mapdelete
函数。它首先会检查 h.flags 标志,如果发现写标位是 1,直接 panic,因为这表明有其他协程同时在进行写操作。
计算 key 的哈希,找到落入的 bucket。检查此 map 如果正在扩容的过程中,直接触发一次搬迁操作。
删除操作同样是两层循环,核心还是找到 key 的具体位置。寻找过程都是类似的,在 bucket 中挨个 cell 寻找。
找到对应位置后,对 key 或者 value 进行“清零”操作:
1
// 对 key 清零
2
if
t
.
indirectkey
{
3
*
(
*
unsafe
.
Pointer
)(
k
)
=
nil
4
}
else
{
5
typedmemclr
(
t
.
key
,
k
)
6
}
7
8
// 对 value 清零
9
if
t
.
indirectvalue
{
10
*
(
*
unsafe
.
Pointer
)(
v
)
=
nil
11
}
else
{
12
typedmemclr
(
t
.
elem
,
v
)
13
}
Copied!
最后,将 count 值减 1,将对应位置的 tophash 值置成
Empty
。
这块源码同样比较简单,感兴起直接去看代码。
Previous
可以边遍历边删除吗
Next
可以对 map 的元素取地址吗
Last modified
2yr ago
Copy link