Slice结构主要包含三个部分:地址、长度、容量
基础结果
- Slice一般都会依赖一个底层数组(数组和切片的最主要区别数组长度不可变;切片长度可变),通过make得到的Slice会直接分配Slice的三大金刚,长度容量可指定,默认为0;通过new得到的Slice不会分配Slice的三大金刚,只是给你个地址,这个地址指向三大金刚的位置,也就是指针,不过这个时候三大金刚也是未初始化的。未初始化,就不能直接操作、赋值之类的(new得到的变量可通过append进行添加值,然后分配三大金刚)
那数组是什么
- Slice底层依赖一个数组,所以数组是咋整的,简单说说。
- Slice三大金刚的地址信息直接指向所依赖的数组,不过不一定是开头元素,可以从数组任意位置开始Slice。
- Slice的长度就是当前存储的个数,而容量就是从Slice首元素到依赖的数组的末元素的长度。比如数组s1=[0,1,2,3,4],切片从’1’开始依赖,s2=[1,2,3],则s2的长度和容量分别为3和4.
扩容规则
- Slice长度可变,现在通过append进行元素添加,s2=append(s2,4,5,6),超过本身依赖数据的长度了,咋整?肯定就要扩容了。
- 直接copy现在Slice各个元素,重新开辟一个内存地址,指向新的内存地址,然后容量重新分配,所以,怎么扩?扩多少?
- 代码优于文字,你看代码肯定更容易理解:
If oldCap * 2 < needCap {
oldCap = needCap
} else {
If oldCap < 1024 {
oldCap *= 2
} else {
oldCap *= 1.25
}
}
附加
- 虽然扩容规则是确定的,但是最终得到的新容量可能和预想的不一样,什么问题呢?
- 每个程序申请新的内存空间,都是由程序本身已经实现的内存管理模块小内来分配的,并不是直接向OS申请。所以,特定的小内会预先向OS申请一系列内存规格,有大有小,如果你的新容量在小内中找不到,它就会给你一个最合适,即最小能满足你大小的内存空间。
- 所以最终的容量值可能会和预想的有些许差异。