概述

Map 作为日常工作最常被使用到的一种数据结构,我们很有必要通过了解它的实现方式来认识其特性,正确的使用它。在 Golang 中,Map 是通过哈希表的方式实现的,接下来我们通过分析源码的方式,来解答我们的疑问。

定义

map的定义位于 src/runtime/map.go 中,首先我们看下 map 和 bucket 的定义:

// 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.
	count     int       // 元素个数,len(map) 返回 count 值
	flags     uint8
	B         uint8     // 位数,最大元素个数为 loadFactor * 2^B
	noverflow uint16    // 溢出个数
	hash0     uint32    // 哈希种子

	buckets    unsafe.Pointer // 桶地址. may be nil if count==0.
	oldbuckets unsafe.Pointer // 旧桶地址
	nevacuate  uintptr        // 搬迁进度,小于 nevacuate 的已经搬迁

	extra *mapextra     // 扩展--+属性
}

// 不是所有 map 都拥有 mapextra 
type mapextra struct {
	// If both key and elem do not contain pointers and are inline, then we mark bucket
	// type as containing no pointers. This avoids scanning such maps.
	// However, bmap.overflow is a pointer. In order to keep overflow buckets
	// alive, we store pointers to all overflow buckets in hmap.extra.overflow and hmap.extra.oldoverflow.
	// 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.
	// The indirection allows to store a pointer to the slice in hiter.
	overflow    *[]*bmap
	oldoverflow *[]*bmap

	// nextOverflow holds a pointer to a free overflow bucket.
	nextOverflow *bmap
}

// Map Bucket
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.
}

标签:

更新时间: