map 的刪除操作
Golang 內(nèi)置了哈希表运挫,總體上是使用哈希鏈表實(shí)現(xiàn)的状共,如果出現(xiàn)哈希沖突,就把沖突的內(nèi)容都放到一個(gè)鏈表里面谁帕。
Golang 還內(nèi)置了delete
函數(shù)峡继,如果作用于哈希表,就是把 map 里面的 key 刪除匈挖。
delete(intMap, 1)
map 的刪除原理
可以直接看源碼碾牌。
我簡單摘幾行:
func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
for ; b != nil; b = b.overflow(t) {
for i := uintptr(0); i < bucketCnt; i++ {
b.tophash[i] = empty
h.count--
}
}
}
外層的循環(huán)就是在遍歷整個(gè) map,刪除的核心就在那個(gè)empty
儡循。它修改了當(dāng)前 key 的標(biāo)記舶吗,而不是直接刪除了內(nèi)存里面的數(shù)據(jù)。
empty = 0 // cell is empty
如何清空整個(gè) map
看了我上面的分析择膝,那么這段代碼可以清空 map 么誓琼?
for k, _ := range m {
delete(m, k)
}
- map 被清空。執(zhí)行完之后調(diào)用
len
函數(shù)调榄,結(jié)果肯定是0踊赠; - 內(nèi)存沒有釋放。清空只是修改了一個(gè)標(biāo)記每庆,底層內(nèi)存還是被占用了筐带;
- 循環(huán)遍歷了
len(m)
次。上面的代碼每一次遍歷都會(huì)刪除一個(gè)元素缤灵,而遍歷的次數(shù)并不會(huì)因?yàn)橹懊看蝿h一個(gè)元素導(dǎo)致減少伦籍。
如何真正釋放內(nèi)存蓝晒?
map = nil
這之后坐等垃圾回收器回收就好了。
如果你用 map 做緩存帖鸦,而每次更新只是部分更新芝薇,更新的 key 如果偏差比較大,有可能會(huì)有內(nèi)存逐漸增長而不釋放的問題作儿。要注意洛二。