go slice切片和append
go slice切片:
切片被初始化的时候,这个切片有一个 len 长度属性和一个 cap 容量属性,
如果切片变量是通过 make([] type, 0) 或 []type{} 创建的时候, 切片的长度和容量就是创建的默认值
如果切片变量是通过 已有数组或切片创建的话,那么,这个切片的长度是切出来的值, 如:
a := make([]int, 10)
b := a[:1]
此时b 切片是通过a切片切出来的, b切片此时的长度就是1, 容量是10, 容量和已有的切片容量共享,
这时候如果操作b切片给b切片appen 添加值的话,如果append 的值没有超过容量值,那么b切片的append操作
就会影响a切片, 如:
a := make([]int, 10)
b := a[:0]
fmt.Println(a, len(a), cap(a)) // 输出 [0 0 0 0 0 0 0 0 0 0] 10 10
fmt.Println(b, len(b), cap(b)) // 输出 [] 0 10
b = append(b, 10, 20)
fmt.Println(a, b) // 输出 [10 20 0 0 0 0 0 0 0 0] [10 20]
b = append(b, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
fmt.Println(a, b) // 输出 [10 20 0 0 0 0 0 0 0 0] [10 20 10 20 30 40 50 60 70 80 90 100]
可以看到, 切片append 的时候,如果append之后的容量没有超出旧容量限制的时候,b切片的修改是会影响到a切片的值的,a,b切片底层类似一个固定长度的链表结构,这个链表有一个固定的长度,b append 的时候貌似是往这个链表添加值,其实如果append 的值的长度没有超过这个链表的长度的时候,append的值是将链表对应的下标值给覆盖了, 如果append 添加的值超过 容量的时候,b 切片的底层链表就会发生改变,应该是先拷贝一份b切片对应的值到新内存上生成一个新的固定长度的链表
切片扩容策略:
当切片容量小于1024的时候,每次扩容都会将容量翻倍, 当切片容量大于或等于1024的时候,每次扩容就是添加本身容量的 1/4 , 1024 应该是一个阈值,防止底层链表结构内存占用过多

浙公网安备 33010602011771号