切片
结构体定义
runtime/slice.go文件中
type slice struct {
array unsafe.Pointer // 数组的指针
len int
cap int
}
扩容
通过append方法添加数据,返回一个新的slice对象,地址和之前不一样。但是原来元素地址是不变的,直到扩容。
package main
import (
"fmt"
)
func main() {
a := make([]int, 1, 2)
b := append(a, 10)
fmt.Println(&a == &b) // 变量地址肯定不同,false
fmt.Println(&a[0] == &b[0]) // true
}
扩容流程
newcap := old.cap
doublecap := newcap + newcap
//这个cap为old.cap+新加元素数量
if cap > doublecap {
newcap = cap
} else {
if old.len < 1024 {
newcap = doublecap
} else {
for newcap < cap {
newcap += newcap / 4
}
}
}
cap是老数组的容量+新加元素数量,即扩容的最小值
如果两倍扩容达不到cap,那么新数组的容量就是这个cap
如果两倍扩容达到了cap,那么根据老数组元素数量是否小于1024来决定扩容容量
1. 如果小于1024,那么正常扩容两倍。
2. 如果大于等于1024,那么循环扩容1.25倍,直到达到或者超过cap,最终结果是扩容值。
之后,通过内存对齐得到最终的容量值。
举个例子
package main
import "fmt"
func main() {
s := []int{1,2}
s = append(s,4,5,6)
fmt.Printf("%d %d",len(s),cap(s))
}
结果是5,6