package main
import "fmt"
func main() {
var s []int
printSlice(s)
// 可在空切片上追加
s = append(s, 0)
printSlice(s)
// 这个切片会按需增长
s = append(s, 1)
printSlice(s)
// 可以一次性添加多个元素
s = append(s, 2, 3, 4)
printSlice(s)
}
func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
分析打印的结果
len=0 cap=0 []
len=1 cap=1 [0]
len=2 cap=2 [0 1]
len=5 cap=6 [0 1 2 3 4]
为何最后一个打印cap=6而不是5的原因是?
// Go 的扩容策略:
// 1. 如果新长度 > 2 * 旧容量,则新容量 = 新长度
// 2. 否则:
// - 如果旧容量 < 256,则新容量 = 2 * 旧容量
// - 如果旧容量 >= 256,则新容量 = 旧容量 * 1.25 + 192
按照策略 5 > 2 * 2
应该是5,为何这里是6? 主要是因为内存对齐问题
理论容量计算:5
但 Go 会将容量向上对齐到内存分配类
int 类型占 8 字节(64位系统) 需要分配:5 * 8 = 40 字节
Go 的内存分配器使用预定义的 size class 常见的 size class(字节): 8, 16, 24, 32, 48, 64, 80, 96, ...
40 字节会被向上对齐到 48 字节
48 / 8 = 6 个 int
所以最终 cap = 6