首页 > golang > golang中slice的扩容机制
2019
07-30

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))
}

 

作者:golang中国
golang中国

本文》有 3308 条评论

留下一个回复