map 的刪除操作
Golang 內置了哈希表,總體上是使用哈希鏈表實現的,如果出現哈希沖突,就把沖突的內容都放到一個鏈表里面。
Golang 還內置了delete
函數,如果作用于哈希表,就是把 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--
}
}
}
外層的循環就是在遍歷整個 map,刪除的核心就在那個empty
。它修改了當前 key 的標記,而不是直接刪除了內存里面的數據。
empty = 0 // cell is empty
如何清空整個 map
看了我上面的分析,那么這段代碼可以清空 map 么?
for k, _ := range m {
delete(m, k)
}
- map 被清空。執行完之后調用
len
函數,結果肯定是0; - 內存沒有釋放。清空只是修改了一個標記,底層內存還是被占用了;
- 循環遍歷了
len(m)
次。上面的代碼每一次遍歷都會刪除一個元素,而遍歷的次數并不會因為之前每次刪一個元素導致減少。
如何真正釋放內存?
map = nil
這之后坐等垃圾回收器回收就好了。
如果你用 map 做緩存,而每次更新只是部分更新,更新的 key 如果偏差比較大,有可能會有內存逐漸增長而不釋放的問題。要注意。