这是我参与「第五届青训营 」伴学笔记创作活动的第 12 天
go slice 详解
slice是类似动态数组的一种数据结构,依托数组实现。
type slice struct{
array unsafe.Pointer
len int
cap int
}
- array指针指向底层数组
- len表示切片长度
- cap表示底层数组容量
使用make创建Slice
- 使用make来创建Slice时,可以同时指定长度和容量
- 创建时底层会分配一个数组,数组的长度即容量
Slice扩容
- 使用append向Slice追加元素时,如果Slice空间不足,将会触发Slice扩容
- 扩容实际上重新一配一块更大的内存
- 将原Slice数据拷贝进新Slice
- 然后返回新Slice
- 扩容后再将数据追加进去
扩容机制
- 当数组容量小于
1024时,每次扩容一倍 - 当数组容量大于等于
1024时,每次扩容约0.25倍,也就是扩容约四分之一的容量 为什么是约呢 这里涉及到内存对齐
slice的追加
使用append向Slice追加元素时, 如果Slice空间不足, 将会触发Slice扩容, 扩容实际上重新一配一块更大的内存, 将原Slice数据拷贝进新Slice, 然后返回新Slice, 扩容后再将数据追加进去。 扩容容量的选择遵循以下规则: 如果原Slice容量小于1024, 则新Slice容量将扩大为原来的2倍; 如果原Slice容量大于等于1024, 则新Slice容量将扩大为原来的1.25倍;
slice的拷贝
使用copy()内置函数拷贝两个切片,但是需要注意的是,copy 会将源切片的数据逐个拷贝到目的切片指向的数组中, 拷贝数量取两个切片长度的最小值。copy不会扩容,只有append才会扩容。 基于以上切片特性。编程过程需要注意: 1.创建切片时可跟据实际需要预分配容量, 尽量避免追加过程中扩容操作, 有利于提升性能; 2.切片拷贝时需要判断实际拷贝的元素个数 3.谨慎使用多个切片操作同一个数组, 以防读写冲突