结论:new(T) 分配一块零值内存并返回指针 *T,适用于任何类型;make(T, ...) 只用于 slice、map、channel 三种引用型结构,返回初始化好的值本身(不是指针),因为它们除了头部还需要初始化底层数据结构(底层数组、哈希桶、队列)。

展开:slice/map/channel 的零值(nil)多数场景不可用或不方便:nil map 写入会 panic,nil channel 收发永久阻塞,nil slice 虽可 append 但通常要预分配容量。make 做的事:slice 创建底层数组并设好 len/cap;map 分配初始桶;channel 创建队列结构。对应地,new 对这三种类型几乎没有用武之地——new(map[string]int) 得到的是指向 nil map 的指针,还得再 make 一次。反过来结构体用 &T{} 字面量比 new(T) 更常见,因为可以直接带字段初始化。易错点:make([]int, 5)make([]int, 0, 5) 的区别——前者 len=5(五个零值),后者 len=0 cap=5(append 追加),混用会产出意料之外的零值前缀。

p := new(int)          // *int,指向 0
s := make([]int, 0, 8) // []int,len 0 cap 8
m := make(map[string]int, 16)
ch := make(chan int, 1)

追问方向:map 预分配容量的意义(减少扩容搬迁)、slice 三种创建方式(字面量/make/new)的底层差异。