map结构是一种比较常用的数据结构,存储k/v映射关系集合,根据key能够快速的查找对应的v。
go的map是基于hashtable实现,冲突解决采用拉链法
map 底层实现结构包含hmap和bmap两个,下面详细说一下(注go.1.17.1版本)
[hmap]
// A header for a Go map.
type hmap struct {
count int //元素个数
flags uint8 //状态标记
B uint8 //可存储(loadFactor * 2^B)个元素
noverflow uint16 //溢出buckets的个数
hash0 uint32 //hash种子
buckets unsafe.Pointer //count为0时,值为nil,否则是Buckets的开始地址
oldbuckets unsafe.Pointer //旧桶的地址,扩容使用
nevacuate uintptr //扩容进度,小于nevacuate的,已迁移完成
extra *mapextra //overflow
}
// mapextra holds fields that are not present on all maps.
type mapextra struct {
// overflow and oldoverflow are only used if key and elem do not contain pointers.
// overflow contains overflow buckets for hmap.buckets.
// oldoverflow contains overflow buckets for hmap.oldbuckets.
overflow *[]*bmap
oldoverflow *[]*bmap
// nextOverflow holds a pointer to a free overflow bucket.
nextOverflow *bmap
}
[bmap]
// A bucket for a Go map.
type bmap struct {
//每个元素的高八位,存储在tophash中
// 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
//keys 隐式定义
//values 隐式定义
//overflow unsafe.Pointer 隐式定义
}
type bmap struct {
topbits [8]uint8
keys [8]keytype
values [8]valuetype
pad uintptr
overflow uintptr
}
低B位高8位
//key定位公式
k := add(unsafe.Pointer(b), dataOffset+i*uintptr(t.keysize))
//value定位公式
e := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.elemsize))
// tophash calculates the tophash value for hash.
func tophash(hash uintptr) uint8 {
top := uint8(hash >> (sys.PtrSize*8 - 8))
if top < minTopHash {
top += minTopHash
}
return top
}
BB为hmap数据结构中的成员8