前言
golang的切片扩容机制是golang面试者绕不开的一扇大门,无论在面试提问,或者面试情景上都绕不开它,今天就说说我理解下的切片扩容。
golang的扩容机制:在go1.18之前有一个临界值为1024,小于1024的时候,切片先两倍扩容,如果两倍扩容后的容量还是不够,就直接以切片需要的容量作为容量。
在go1.18之后,临界值换成了256,小于256和前面相同,大于256公式变为(oldcap+3*256)/4这个公式的值随着oldcap的越来越大,从2一直接近1.25,相对于1.18之前可以更平滑的过渡。
上面就是切片扩容的基本规则机制,但还有一个小的规则,下面就来看看
发现问题
看下面一行代码
运行结果如下
出现上面的结果原因是,刚开始切片容量为1,两倍扩容之后,变为2,但是2不够,所以变为所需要的容量3,后面在加4个数字,继续扩容,2倍之后是6,但是6不够应该变为需要的容量,应该为7,为什么是8呢
解决问题
先贴一下源代码,下面第一段代码是扩容机制的基础代码(1.18之前)
下面是造成上面原因的代码
下面是1.18之后的基础扩容机制
从上面代码分析之后,造成7变成8的原因就在这个roundupsize函数上面,它有一个计算公式
capmem = roundupsize(uintptr(newcap) * ptrSize)
newcap = int(capmem / ptrSize)
其中 ptrSize
在 64 位机器下的大小为 8。 而此时 newcap
的值为 7,所以传入到 roundupsize
函数内部的值为 7 * 8 = 56
。接着看看 roundupsize
的内部:
func roundupsize(size uintptr) uintptr {
if size < _MaxSmallSize {
if size