golang中slice的扩容机制

傷城~ 2022-09-07 15:51 190阅读 0赞

文章目录

  • 简介
  • 结论
  • 关于 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 是真实长度,但是其容量仍然表示原数组容量

  1. func main() {
  2. arr := [4]int{
  3. 1, 2, 3, 4}
  4. sli := arr[0:2]
  5. // 2 和 4
  6. fmt.Println(len(sli), cap(sli))
  7. }

关于 cap 扩容

多数情况下,我们的原切片长度 len 是小于 1024 的,所以我们会遇见下面情形的代码。下面代码最新输出是 5 和 8,明显可以发现因为 len < 1024,然后 cap 从原来容量直接变成了 2 倍值

  1. func main() {
  2. arr := [4]int{
  3. 1, 2, 3, 4}
  4. sli := arr[0:2]
  5. // 4 和 4
  6. fmt.Println(len(sli), cap(sli))
  7. // 需要扩容了
  8. sli := append(sli, 5)
  9. // 5 和 8
  10. fmt.Println(len(sli), cap(sli))
  11. }

那如果 len 本身就是 1024 再扩容呢?我们看看下面代码。我们知道 make 时候 sli 的 len 为 1024 并且 cap 为 1024,但是扩容一次之后发现,len 变成了 1025,但是 cap 变成了 1280,为什么是 1280 呢?因为 len 已经是 1024 了,所以扩容后,容积需要增加 1/4,容积增加 1/4 且新 cap 没有溢出,所以 cap 就从 1024 就变成 1280 了

  1. func main() {
  2. sli := make([]int, 1024, 1024)
  3. sli = append(sli, 1)
  4. // 1025 和 1280
  5. fmt.Println(len(sli), cap(sli))
  6. }

发表评论

表情:
评论列表 (有 0 条评论,190人围观)

还没有评论,来说两句吧...

相关阅读

    相关 606-Golangslice切片

    slice切片 切片是数组的一部分,slice本身是数组的引用!!! 也就是说,如果修改slice的"数据",array数组本身也会变 切片声明 v