1. 程式人生 > >總結golang之map

總結golang之map

ade itl 沒有 fas mark 以及 ice 保護 ast

總結golang之map

2017年04月13日 23:35:53 趁年輕造起來 閱讀數:18637 標簽: golangmapgo 個人分類: golang 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/Soooooooo8/article/details/70163475

0x01 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,

補充

  1. 不像Java可以為class自定義hashcode方法,以及C++可以重載==操作符,golang map**不支持**==重載或者使用自定義的hash方法。因此,如果想要把struct用作map的key,就必須保證struct不包含slice, map, func
  2. 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,

  1. maptype用來保存map的類型信息,包括key、elem(value)的類型描述器,keysize,valuesize,bucketsize等;
  2. 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;
    技術分享圖片
  3. 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