持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情
生命不息,学习不止
题外话
今天周五了,这两天太阳可能休假了,又是阴天的一天,这个天也太让人犯困了呀,但是一想到明天就可以放假了,一觉睡到自然醒就很激动啊,哈哈哈
废话不多说,上货
上回讲了一下slice切片的底层结构和拷贝,今天就来说说slice切片的扩容机制
slice扩容机制
基本都知道数组是一个固定长度的结构,要在初始时声明长度,
而slice切片是动态的,可通过append()函数向切片中追加元素,甚至可以直接追加一个切片来将切片中所有的元素加入进去,举个例子
可以看到slice切片内的数组越来越多,但slice声明时不可能声明一个无限长的长度,所以一定是有一个默认长度, 当元素到一定数量后会触发扩容
要想明白原理还是直接看源码,负责slice切片扩容的核心函数是 growslice(),核心代码如下
func growslice(et *_type, old slice, cap int) slice {
//...............
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
const threshold = 256
if old.cap < threshold {
newcap = doublecap
} else {
for 0 < newcap && newcap < cap {
newcap += (newcap + 3*threshold) / 4
}
if newcap <= 0 {
newcap = cap
}
}
}
//............
}
可以看到如果向slice切片中添加元素的容量大于原本容量的二倍,就会变成添加后的容量
如果添加后的容量小于原本容量的二倍并小于1024,仍然为原容量的二倍
但如果添加后的容量小于原本容量的二倍并大于1024,则变为原容量的1.25倍
其实growslice()函数的后半部分还根据et对能容量进行了内存对齐
对齐之后会为新的slice预留一部分空间,也就是所说的预留了一部分buffer
最后便是将原slice的元素copy到新的slice切片中,并将新添加的元素加入到新slice切片中
你以为结束了
下一篇我们讲一下append()方法与...
大家看完发现有什么错误,写在下面吧!跟我黑虎阿福比划比划!