golang语法专题:slice、map

参考:

https://blog.csdn.net/weixin_52690231/article/details/124827013(Go1.17、1.18源码分析slice扩容规则)

https://www.jianshu.com/p/7782d82f5154(go map实现原理)

https://www.cnblogs.com/qcrao-2018/p/10903807.html(深度揭秘go map)

slice

源码路径:go/src/runtime/slice.go

Go1.17源码分析slice扩容规则

func growslice(et *_type, old slice, cap int) slice {
  ...
  
  newcap := old.cap
  doublecap := newcap + newcap
  if cap > doublecap {
    newcap = cap
  } else {
    if old.cap < 1024 {
      newcap = doublecap
    } else {
      // Check 0 < newcap to detect overflow
      // and prevent an infinite loop.
      for 0 < newcap && newcap < cap {
        newcap += newcap / 4
      }
      // Set newcap to the requested cap when
      // the newcap calculation overflowed.
      if newcap <= 0 {
        newcap = cap
      }
    }
  }
  
  ...
}

 

代码的扩容策略可以简述为以下三个规则:
1.当期望容量 > 两倍的旧容量时,直接使用期望容量作为新切片的容量
2.如果旧容量 < 1024(注意这里单位是元素个数),那么直接翻倍旧容量
3.如果旧容量 > 1024,那么会进入一个循环,每次增加25%直到大于期望容量

Go1.18源码分析slice扩容规则

到了Go1.18时,又改成不和1024比较了,而是和256比较;并且扩容的增量也有所变化

newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
  newcap = cap
} else {
  const threshold = 256
  if old.cap < threshold {
    newcap = doublecap
  } else {
    // Check 0 < newcap to detect overflow
    // and prevent an infinite loop.
    for 0 < newcap && newcap < cap {
      // Transition from growing 2x for small slices
      // to growing 1.25x for large slices. This formula
      // gives a smooth-ish transition between the two.
      newcap += (newcap + 3*threshold) / 4
    }
    // Set newcap to the requested cap when
    // the newcap calculation overflowed.
    if newcap <= 0 {
      newcap = cap
    }
  }
}

 

 

什么是Map

最通俗的话说Map是一种通过key来获取value的一个数据结构,其底层存储方式为数组,在存储时key不能重复,当key重复时,value进行覆盖,我们通过key进行hash运算(可以简单理解为把key转化为一个整形数字)然后对数组的长度取余,得到key存储在数组的哪个下标位置,最后将key和value组装为一个结构体,放入数组下标处。

Go中Map的实现原理

源码路径:go/src/runtime/map.go

知其然,知其所以然。map的源码位于 src/runtime/map.go中 ,map同样也是数组存储的的,每个数组下标处存储的是一个bucket,这个bucket的类型见下面代码,每个bucket中可以存储8个kv键值对,当每个bucket存储的kv对到达8个之后,会通过overflow指针指向一个新的bucket,从而形成一个链表,

底层数据结构体

 

创建map

 

写入map

 

读取流程

 

删除流程

 

posted @ 2022-07-21 10:43  指令跳动  阅读(52)  评论(0编辑  收藏  举报