golang中slice的扩容机制
文章目录
- 简介
- 结论
- 关于 len & cap
- 关于 cap 扩容
简介
slice 是 golang 中的数组切片,可以理解成是一种动态数组,一般通过 make 声明时候,会指定其 len 和 cap。一般我们常常使用 append 函数时候当 len 超过 cap 时候就会进行扩容处理
结论
我们先说结论
- 当所需容量 cap 大于原先容量 cap 的 2 倍,则最终申请 cap 容量为当前所需容量
- 当所需要容量 cap 没有大于原先容量 cap 2 倍时,且若原切片长度 len 小于 1024 时候,最终申请容量 cap 为原先容量 2 倍,否则最终申请容量 cap 的计算方式为:cap 每次增加 1/4 的容量,直到大于新容量大小时为止,最后判定新容量是否溢出,若溢出最终申请的容量即为最终容量
关于 len & cap
下面这段代码,最后输出结果是 2 和 4,也就是说从数组切出来的切片,其 len 是真实长度,但是其容量仍然表示原数组容量
func main() {
arr := [4]int{
1, 2, 3, 4}
sli := arr[0:2]
// 2 和 4
fmt.Println(len(sli), cap(sli))
}
关于 cap 扩容
多数情况下,我们的原切片长度 len 是小于 1024 的,所以我们会遇见下面情形的代码。下面代码最新输出是 5 和 8,明显可以发现因为 len < 1024,然后 cap 从原来容量直接变成了 2 倍值
func main() {
arr := [4]int{
1, 2, 3, 4}
sli := arr[0:2]
// 4 和 4
fmt.Println(len(sli), cap(sli))
// 需要扩容了
sli := append(sli, 5)
// 5 和 8
fmt.Println(len(sli), cap(sli))
}
那如果 len 本身就是 1024 再扩容呢?我们看看下面代码。我们知道 make 时候 sli 的 len 为 1024 并且 cap 为 1024,但是扩容一次之后发现,len 变成了 1025,但是 cap 变成了 1280,为什么是 1280 呢?因为 len 已经是 1024 了,所以扩容后,容积需要增加 1/4,容积增加 1/4 且新 cap 没有溢出,所以 cap 就从 1024 就变成 1280 了
func main() {
sli := make([]int, 1024, 1024)
sli = append(sli, 1)
// 1025 和 1280
fmt.Println(len(sli), cap(sli))
}
还没有评论,来说两句吧...