文章目录
- 简介
- 结论
- 关于 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 的容量,直到大于新容量大小时为止,最后判定新容量是否溢出,若溢出最终申请的容量即为最终容量
下面这段代码,最后输出结果是 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)) }
《本文》有 3308 条评论