Golang如何快速刪除map所有元素
1. 所有Go版本通用方法
重新申請一個新的map,舊的map交給GC去回收。
a := make(map[string]int) a["a"] = 1 a["b"] = 2 // clear all a = make(map[string]int)
2. Go 1.11版本以上用法
通過Go的內(nèi)部函數(shù)mapclear方法刪除。
這個函數(shù)并沒有顯示的調(diào)用方法,當你使用for循環(huán)遍歷刪除所有元素時,Go的編譯器會優(yōu)化成Go內(nèi)部函數(shù)mapclear。
package main func main() { m := make(map[byte]int) m[1] = 1 m[2] = 2 for k := range m { delete(m, k) } }
把上述源代碼直接編譯成匯編(默認編譯是會優(yōu)化的):
go tool compile -S map_clear.go
可以看到編譯器把源碼9行的for循環(huán)直接優(yōu)化成了mapclear去刪除所有元素。
如下:
再來看看關(guān)閉優(yōu)化后的結(jié)果:
go tool compile -l -N -S map_clear.go
關(guān)閉優(yōu)化選項后,Go編譯器直接通過循環(huán)遍歷來刪除map里面的元素。
由上可知,遍歷刪除在經(jīng)過編譯器優(yōu)化后會調(diào)用mapclear一次性刪除map所有元素,那這個mapclear函數(shù)是如何實現(xiàn)的,效率如何?
mapclear源碼實現(xiàn)
這部分代碼涉及到內(nèi)存管理和GC,只能看懂個大概,后續(xù)再補充。
實現(xiàn)思路
- 清空統(tǒng)計數(shù)據(jù),如元素個數(shù)、溢出數(shù)等。
- 重新申請一個新的extra,原有的extra交給GC。
- 釋放桶內(nèi)存塊。
func mapclear(t *maptype, h *hmap) { ... // 把oldbuckets置nil,如果有oldbuckets就讓GC處理 h.oldbuckets = nil // 初始化溢出數(shù)、元素個數(shù) h.nevacuate = 0 h.noverflow = 0 h.count = 0 // 重新申請一個新的extra,舊的交給GC回收 if h.extra != nil { *h.extra = mapextra{} } // 清空bucket _, nextOverflow := makeBucketArray(t, h.B, h.buckets) ... } func makeBucketArray(t *maptype, b uint8, dirtyalloc unsafe.Pointer) (buckets unsafe.Pointer, nextOverflow *bmap) { base := bucketShift(b) nbuckets := base ... // 沒有分配過內(nèi)存,則申請一個新的 if dirtyalloc == nil { buckets = newarray(t.bucket, int(nbuckets)) } else { // 直接釋放整個buckets buckets = dirtyalloc size := t.bucket.size * nbuckets if t.bucket.kind&kindNoPointers == 0 { memclrHasPointers(buckets, size) } else { memclrNoHeapPointers(buckets, size) } } ... }
總結(jié)
使用mapclear方法清空map時,做的工作就是初始化和釋放申請內(nèi)存塊,效率很高。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
一文理解Goland協(xié)程調(diào)度器scheduler的實現(xiàn)
本文主要介紹了Goland協(xié)程調(diào)度器scheduler的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-06-06