Go slice扩容机制?
Go 1.18版本之前
扩容会发生在slice append的时候,当slice的cap不足以容纳新元素,就会进行扩容,扩容规则如下
- 如果新申请容量比两倍原有容量大,那么扩容后容量大小 为 新申请容量
- 如果原有 slice 长度小于 1024, 那么每次就扩容为原来的 2 倍
- 如果原 slice 长度大于等于 1024, 那么每次扩容就扩为原来的 1.25 倍
func main() {
slice1 := []int{1, 2, 3}
for i := 0; i < 16; i++ {
slice1 = append(slice1, 1)
fmt.Printf("addr: %p, len: %v, cap: %v
", slice1, len(slice1), cap(slice1))
}
}
addr: 0xc00001a120, len: 4, cap: 6
addr: 0xc00001a120, len: 5, cap: 6
addr: 0xc00001a120, len: 6, cap: 6
addr: 0xc000060060, len: 7, cap: 12
addr: 0xc000060060, len: 8, cap: 12
addr: 0xc000060060, len: 9, cap: 12
addr: 0xc000060060, len: 10, cap: 12
addr: 0xc000060060, len: 11, cap: 12
addr: 0xc000060060, len: 12, cap: 12
addr: 0xc00007c000, len: 13, cap: 24
addr: 0xc00007c000, len: 14, cap: 24
addr: 0xc00007c000, len: 15, cap: 24
addr: 0xc00007c000, len: 16, cap: 24
addr: 0xc00007c000, len: 17, cap: 24
addr: 0xc00007c000, len: 18, cap: 24
addr: 0xc00007c000, len: 19, cap: 24
Go 1.18版本切片扩容
Go1.18不再以1024为临界点,而是设定了一个值为256的threshold
,以256为临界点;超过256,不再是每次扩容1/4,而是每次增加(旧容量+3*256)/4;
- 当新切片需要的容量cap大于两倍扩容的容量,则直接按照新切片需要的容量扩容;
- 当原 slice 容量 < threshold 的时候,新 slice 容量变成原来的 2 倍;
- 当原 slice 容量 > threshold,进入一个循环,每次容量增加(旧容量+3*threshold)/4。
公式如下: