Go中map是一个指针,占用8个字节,指向hmap结构

hmap包含若干个结构为bmap的数组,每个bmap底层都是采用链表结构,bmap通常叫做bucket

hmap结构:

type hmap struct{
    count int //元素数量
  flags uint8 //状态标志
  B uint8 //buckets的对数,如果B=5,则buckets的数量=2^5 = 32
  noverflow uint16 //溢出桶的数量
  hash0  uint32 //hash种子
  buckets unsafe.Pointer //指向buckets数组的指针,数组长度为2^B
  oldbuckets  unsafe.Pointer //如果发生扩容,指向老的buckets数组的指针,
  //oldbuckets数组大小为buckets数组长度的一半,未发生扩容时是null
  nevacuate  uintptr //表示扩容速度,小于此地址的都已经扩容完成
  extra *mapextra //存储溢出桶
}

bmap结构:

type bmap struct {
    tophash [bucketCnt]uint8
  //len为8的数组,用于快速定位key是否在这个bmap中
  //一个桶油8个槽,如果key的高8位在tophash中,则表示该key在这个捅中
}

bmap就是我们所说的桶,一个桶最多存放8个key,这些key之所以存放在一个桶,是因为经过hash计算之后,hash结果的低8位相同,在桶内又会根据hash结果的高8位来决定key到底落入那个位置(共有8个位置)。

bmap结构的定义是一个静态结构,在编译过程中,会扩展成下面的结构:

type bmap struct {
    tophash [8]uint8
  keys  [8]keytype
  values [8]elementtype
  overflow uintptr //指向下一个bmap,溢出捅存放在hmap的extra字段中
}

注意key和value是分开放的,这样的形式,当key和value的类型不一样的时候,key和value占用的字节大小不一样,key/value这种形式可能会因为内存对齐而浪费空间,所以分开放更节省内存空间。

mapextra的结构:

type mapextra struct {
    overflow *[]*bmap //包含的是bmap.buckets的overflow的bucket 
    oldoverflow *[]*bmap//包含的扩容时的是bmap.oldbuckets的overflow的bucket 
    nextoverflow *bmap //指向空闲的overflow bucket的指针
}

当map中的key、value都不含指针时,bmap将完全不包含指针,bmap指向溢出桶的字段overflow是uintptr类型,为了防止overflow被gc掉,所以需要mapextra.overflow将它保存起来。

map遍历

map遍历是无序的,原因有2点:

  • map的遍历时,并不是从0号bucket开始遍历,而是从一个随机序号的bucket,再从其中随机的key开始遍历
  • map在扩容后,可能一部分key已经搬迁到了新的内存,此时key就是无序的了

map是非线程安全的,因为Go官方认为,map的典型应用场景是不需要并发访问的,而不是为了小部分情况,导致大部分程序付出加锁的代价。map可以并发读,但不能并发写,否则会panic。

map的扩容

扩容时机

在向map插入新key的时候,会进行2个条件检查,如果符合就会触发扩容

扩容条件

  1. 超过负载:map元素个数 > 6.5 *桶个数
  2. 溢出桶太多

    1. 当桶总数 < 2 ^ 15时,如果溢出桶总数 > 桶总数,则认为溢出桶太多了
    2. 当桶总数 ≥ 2 ^ 15时,如果溢出桶总数 > 2 ^ 15时,则认为溢出桶太多了

扩容机制

  1. 双倍扩容:针对扩容条件1,新建buckets数组,新的buckets大小为原来的2倍,然后旧的buckets数据搬迁到新的buckets,称之为双倍扩容
  2. 等量扩容:针对扩容条件2,并不扩大容量,buckets数量维持不变,将原来的元素搬迁到一起,将松散的键值对重新排列,使得同一个bucket中的key排列更紧密,节省空间,提高bucket利用率

元素搬迁

并不会在扩容之后立马搬迁,而是在插入或者对key的修改和删除操作时,都会尝试进行搬迁,一次最多搬迁2个bucket

标签: none

已有 33 条评论

  1. 这篇文章不错!

  2. 这篇文章不错!

  3. 这篇文章如同一首动人的乐章,触动了读者内心深处的柔软。

  4. 作者以简洁明了的语言,传达了深刻的思想和情感。

  5. 作者的才华横溢,让这篇文章成为了一篇不可多得的艺术品。

  6. 若能在案例选择上更贴近现实,说服力会进一步提升。

  7. 情感真挚自然,字里行间传递出强烈的感染力。

  8. 对权力结构的解构充满勇气与智慧。

  9. 瑕不掩瑜,稍加打磨必成佳作。

  10. ?叙事类评语?

  11. 实验数据可增加误差分析以提高严谨性。

  12. 情感真挚自然,字里行间传递出强烈的感染力。

  13. 文化符号解读精准,展现独特审美。

  14. 情感表达稍显含蓄,可适当强化渲染。

  15. 在畅想未来时需警惕乌托邦式理想化。

  16. 作者的观点新颖且实用,让人在阅读中获得了新的思考和灵感。

  17. 作者以简洁明了的语言,传达了深刻的思想和情感。

  18. 《盲(高清特别版)》爱情片高清在线免费观看:https://www.jgz518.com/xingkong/147936.html

  19. 你的才华让人惊叹,你是我的榜样。 https://www.yonboz.com/video/72855.html

  20. 你的才华横溢,让人敬佩。 http://www.55baobei.com/jCLyc5kBOQ.html

  21. 《红莓》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/120561.html

  22. 你的才华横溢,让人敬佩。 http://www.55baobei.com/xB0zjRP3d1.html

  23. 你的才华横溢,让人敬佩。 http://www.55baobei.com/SMxMtZnm9c.html

  24. 《红莓》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/120561.html

  25. 《离开拉斯维加斯国语》爱情片高清在线免费观看:https://www.jgz518.com/xingkong/21965.html

  26. 你的文章让我感受到了不一样的视角,非常精彩。 https://www.4006400989.com/qyvideo/81716.html

  27. 你的文章让我心情愉悦,真是太棒了! https://www.4006400989.com/qyvideo/94175.html

  28. 真棒!

  29. 你的文章让我感受到了快乐,每天都要来看一看。 http://www.55baobei.com/UjhE32tSfS.html

  30. 你的文章让我学到了很多技能,非常实用。 https://www.yonboz.com/video/71959.html

  31. 兄弟写的非常好 https://www.cscnn.com/

  32. 不错不错,我喜欢看 https://www.ea55.com/

  33. 想想你的文章写的特别好https://www.jiwenlaw.com/

添加新评论