總結golang之map
阿新 • • 發佈:2018-12-03
ade itl 沒有 fas mark 以及 ice 保護 ast
和
總結golang之map
2017年04月13日 23:35:53 趁年輕造起來 閱讀數:18637 個人分類: golang 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/Soooooooo8/article/details/701634750x01 map基本操作
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
0x02 map鍵類型
支持 == 操作符的類型有:
- boolean,
- numeric,
- string,
- pointer,
- channel,
- interface(as long as dynamic type supports equality),
- 以及只包含上述類型的array和struct
不支持 == 操作符的類型有:
- slice,
- map,
- func,
補充
- 不像Java可以為class自定義hashcode方法,以及C++可以重載==操作符,golang map**不支持**==重載或者使用自定義的hash方法。因此,如果想要把struct用作map的key,就必須保證struct不包含slice, map, func
- golang為uint32、uint64、string提供了fast access,使用這些類型作為key可以提高map訪問速度,詳見hashmap_fast.go
0x03 map並發
map不是並發安全的,通常使用sync.RWMutex保護並發map
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
0x04 map小技巧
4.1. 利用value類型的零值
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
4.2. map[k1]map[k2]v 對比 map[struct{k1, k2}]v
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
0x05 map實現細節淺析
5.1. 如何計算hash值
golang為每個類型定義了類型描述器_type
,並實現了hashable類型的_type.alg.hash
_type.alg.equal
。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
5.2. map實現結構
map的實現主要有三個struct,
- maptype用來保存map的類型信息,包括key、elem(value)的類型描述器,keysize,valuesize,bucketsize等;
- hmap - A header for a Go map. hmap保存了map的實例信息,包括count,buckets,oldbuckets等;buckets是bucket的首地址,用hash值的低h.B位
hash & (uintptr(1)<<h.B - 1)
計算出key所在bucket的index; - bmap - A bucket for a go map. bmap只有一個域
tophash [bucketCnt]uint8
,它保存了key的hash值的高8位uint8(hash >> (sys.PtrSize*8 - 8))
;一個bucket包括一個bmap(tophash數組),緊跟的bucketCnt個keys和bucketCnt個values,以及一個overfolw指針。
makemap根據maptype中的信息初始化hmap
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
5.3. 如何訪問map
golang的maptype保存了key的類型描述器,以供訪問map時調用key.alg.hash
, key.alg.equal
。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
5.4. map擴張
這部分留待以後有機會再續。這裏暫時附上Keith Randall的slide作為參考。
0x06 map建議
- 如果知道size,預先分配資源
make(map[int]int, 1000)
- uint32, uint64, string作為鍵,非常快
- 清理map:
for k:= range m { delete(m, k) }
- key和value中沒有指針可以使GC scanning更快
總結golang之map