golang中slice的扩容机制
阅读此⽂档默认已经掌握了slice的动态数组原理,如果没有此认知,请阅读(本⽂也是在此链接基础上扩展⼀些解释说明)。
扩容
slice这种数据结构便于使⽤和管理数据集合,可以理解为是⼀种“动态数组”,slice也是围绕动态数组的概念来构建的。既然是动态数组,那么slice是如何扩容的呢?
请记住以下两条规则:
如果切⽚的容量⼩于1024个元素,那么扩容的时候slice的cap就翻番,乘以2;⼀旦元素个数超过1024个元素,增长因⼦就变成1.25,即每次增加原来容量的四分之⼀。
如果扩容之后,还没有触及原数组的容量,那么,切⽚中的指针指向的位置,就还是原数组,如果扩容之后,超过了原数组的容量,那么,Go就会开辟⼀块新的内存,把原来的值拷贝过来,这种情况丝毫不会影响到原数组。
知道了⼀下规则,请看下⾯程序,试问输出结果:
1 2 3 4 5 6 7 8 9 10import (
"fmt"
)
func main(){
array := [4]int{10, 20, 30, 40}
slice := array[0:2]
newSlice := append(append(append(slice, 50), 100), 150)    newSlice[1] += 1
fmt.Println(slice)
}
输出:
1[10 20]
上述程序中,由于扩容了三次,超过了原始数组的容量,所以把原始数组拷贝过来,对新切⽚的修改并不影响原始数组的值。从⽽打印原始数组不影响原数组。
如果:
1 2 3 4 5 6 7 8 9 10import (
"fmt"
)
func main(){
array := [4]int{10, 20, 30, 40}
slice := array[0:2]
newSlice := append(append(slice, 50), 100)    newSlice[1] += 1
fmt.Println(slice)
}
则输出:
1[10 21]
go字符串转数组由于扩容了两次,没有超过原始数组的容量,所以新切⽚指针还是指向原始数组,对新切⽚的修改既对原始数组的修改。从⽽打印原始数组为修改过的原数组。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。