Slice数据结构
type slice struct {
array unsafe.Pointer #指向底层数组的指针
len int #切片长度
cap int #底层数组容量
}
创建切片的方式
slice := make([]int, 5, 10) #长度5 容量10
fmt.Printf("%#v \n", slice) #[]int{0, 0, 0, 0, 0}
---------------------------------------------------------------------------------
slice := make([]int, 0) #长度0 容量 0
fmt.Printf("%#v \n", slice) #[]int{} 指针指向一个空的数组
---------------------------------------------------------------------------------
var slice []int #长度0 容量 0
fmt.Printf("%#v \n", slice) #[]int(nil) 指针指向空
---------------------------------------------------------------------------------
array := [10]int{} #定义长度为10的数组
slice := array[5:7] #长度2 容量 5(array[5],array[6]有效,可以直接访问)
append操作
单个放入的情况下,长度没超过容量,直接放,底层数组不会扩容
如果长度没超过容量,底层数组会扩容,有特定的扩容算法,扩容后再放入原长度+1
重点:扩容策略
预估需要容量:newCap
,扩容后的容量:fianlCap
func main() {
slice := []int{1, 2} #len=2 cap=2
slice = append(slice, 1, 2, 3) #len=5 cap=6
fmt.Println("len(slice) = ", len(slice)) #len(slice) = 5
fmt.Println("cap(slice) = ", cap(slice)) #cap(slice) = 6
}
原始容量为2 添加3个元素,预估容量为:5,扩容后的容量:6
以上分配究竟是为什么呢?
第一步: 计算预估容量newCap
第二步: newCap个元素需要多大内存
需要这么大内存 = newCap
X 元素类型大小 = (5 * 8)= 40 byte
64位操作系统int类型 = int64 = 64bit = 8 byte
实际分配中,由于内存管理模块的存在,并不会直接对于分配给需要的大小,而是会在内存管理模块的已经向操作系统申请好的一系列常用大小的内存空间(8byte,16byte,32byte,48byte,64byte…)中,选择合适大小的空间分配出去。
因此40byte <= 48byte,选择48byte分配出去,6int的内存大小。