我们知道go的内置函数make返回一个Type类型的对象
func make(Type, size IntegerType) Type
然后直接上源码:
// Builds a type representing a Hmap structure for the given map type. // Make sure this stays in sync with ../../../../runtime/hashmap.go! func hmap(t *Type) *Type { if t.MapType().Hmap != nil { return t.MapType().Hmap } bucket := mapbucket(t) var field [8]*Field field[0] = makefield("count", Types[TINT]) field[1] = makefield("flags", Types[TUINT8]) field[2] = makefield("B", Types[TUINT8]) field[3] = makefield("hash0", Types[TUINT32]) field[4] = makefield("buckets", Ptrto(bucket)) field[5] = makefield("oldbuckets", Ptrto(bucket)) field[6] = makefield("nevacuate", Types[TUINTPTR]) field[7] = makefield("overflow", Types[TUNSAFEPTR]) h := typ(TSTRUCT) h.Noalg = true h.Local = t.Local h.SetFields(field[:]) dowidth(h) t.MapType().Hmap = h h.StructType().Map = t return h }
// MapType contains Type fields specific to maps. type MapType struct { Key *Type // Key type Val *Type // Val (elem) type Bucket *Type // internal struct type representing a hash bucket Hmap *Type // internal struct type representing the Hmap (map header object) Hiter *Type // internal struct type representing hash iterator state } // MapType returns t's extra map-specific fields. func (t *Type) MapType() *MapType { t.wantEtype(TMAP) return t.Extra.(*MapType) }// A header for a Go map. type hmap struct { // Note: the format of the Hmap is encoded in ../../cmd/internal/gc/reflect.go and // ../reflect/type.go. Don't change this structure without also changing that code! count int // # live cells == size of map. Must be first (used by len() builtin) flags uint8 B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items) hash0 uint32 // hash seed buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0. oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing nevacuate uintptr // progress counter for evacuation (buckets less than this have been evacuated) // If both key and value 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.overflow. // Overflow is used only if key and value do not contain pointers. // overflow[0] contains overflow buckets for hmap.buckets. // overflow[1] contains overflow buckets for hmap.oldbuckets. // The first indirection allows us to reduce static size of hmap. // The second indirection allows to store a pointer to the slice in hiter. overflow *[2]*[]*bmap }func hashGrow(t *maptype, h *hmap) { if h.oldbuckets != nil { throw("evacuation not done in time") } oldbuckets := h.buckets newbuckets := newarray(t.bucket, 1<<(h.B+1)) flags := h.flags &^ (iterator | oldIterator) if h.flags&iterator != 0 { flags |= oldIterator } // commit the grow (atomic wrt gc) h.B++ h.flags = flags h.oldbuckets = oldbuckets h.buckets = newbuckets h.nevacuate = 0 if h.overflow != nil { // Promote current overflow buckets to the old generation. if h.overflow[1] != nil { throw("overflow is not nil") } h.overflow[1] = h.overflow[0] h.overflow[0] = nil } // the actual copying of the hash table data is done incrementally // by growWork() and evacuate(). }源码解析:对于map类型Type实例中,包含一个MapType结构指针,而MapType中包含了Hmap结构指针,Hmap指向一个hmap结构体,该结构体中的buckets和oldbuckets对应着真实的key/value数据,map重新分桶时,buckets改变,但hmap的地址不会改变图示:Type{ //A实例Hmap *Type //指向hmap}//hmap在make时才会生成type hmap struct {map实例A传参后, buckets unsafe.Pointer -----------> 类型数(实际数据key/value)在函数内得到A的拷贝实例B oldbuckets unsafe.Pointer
}Type{ //B实例Hmap *Type //指向A指向的hmap}