go
// A header for a Go map.
type hmap struct {
// Note: the format of the hmap is also encoded in cmd/compile/internal/reflectdata/reflect.go.
// Make sure this stays in sync with the compiler's definition.
// 元素个数,len(map)
count int // # live cells == size of map. Must be first (used by len() builtin)
// 标记是否有线程正在写
flags uint8
// buckets 的对数 log_2
B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
// overflow的bucket大致数量
noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
// 哈希的种子,它能为哈希函数的结果引入随机性,这个值在创建哈希表时确定,并在调用哈希函数时作为参数传入
hash0 uint32 // hash seed
// buckets 数组,大小为 2^B
buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
// 旧map,不为nil时表示正在扩容
oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
// 扩容进度,小于此地址的 buckets 是已经迁移完成的
nevacuate uintptr // progress counter for evacuation (buckets less than this have been evacuated)
extra *mapextra // optional fields
}
buckets 是一个指针,最终它指向的是一个结构体:
go
// A bucket for a Go map.
type bmap struct {
// tophash generally contains the top byte of the hash value
// for each key in this bucket. If tophash[0] < minTopHash,
// tophash[0] is a bucket evacuation state instead.
tophash [bucketCnt]uint8
// Followed by bucketCnt keys and then bucketCnt elems.
// NOTE: packing all the keys together and then all the elems together makes the
// code a bit more complicated than alternating key/elem/key/elem/... but it allows
// us to eliminate padding which would be needed for, e.g., map[int64]int8.
// Followed by an overflow pointer.
}
运行时:
go
type bmap struct {
topbits [8]uint8
keys [8]keytype
values [8]valuetype
pad uintptr
overflow uintptr
}
bmap 就是我们常说的"桶",桶里面会最多装 8 个 key,这些 key 之所以会落入同一个桶,是因为它们经过哈希计算后,哈希结果是"一类"的。在桶内,又会根据 key 计算出来的 hash 值的高 8 位来决定 key 到底落入桶内的哪个位置(一个桶内最多有8个位置)。