阅读此文档默认已经掌握了slice的动态数组原理,如果没有此认知,请阅读https://i6448038.github.io/2018/08/11/array-and-slice-principle/ (本文也是在此链接基础上扩展一些解释说明)。
扩容
slice这种数据结构便于使用和管理数据集合,可以理解为是一种“动态数组”,slice
也是围绕动态数组的概念来构建的。既然是动态数组,那么slice是如何扩容的呢?
请记住以下两条规则:
- 如果切片的容量小于1024个元素,那么扩容的时候slice的cap就翻番,乘以2;一旦元素个数超过1024个元素,增长因子就变成1.25,即每次增加原来容量的四分之一。
- 如果扩容之后,还没有触及原数组的容量,那么,切片中的指针指向的位置,就还是原数组,如果扩容之后,超过了原数组的容量,那么,Go就会开辟一块新的内存,把原来的值拷贝过来,这种情况丝毫不会影响到原数组。
知道了一下规则,请看下面程序,试问输出结果:
1
|
import (
|
输出:
1
|
[10 20]
|
上述程序中,由于扩容了三次,超过了原始数组的容量,所以把原始数组拷贝过来,对新切片的修改并不影响原始数组的值。从而打印原始数组不影响原数组。
如果:
1
|
import (
|
则输出:
1
|
[10 21]
|
由于扩容了两次,没有超过原始数组的容量,所以新切片指针还是指向原始数组,对新切片的修改既对原始数组的修改。从而打印原始数组为修改过的原数组。