go语言map的内部实现及传参

我们知道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
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值