new只分配零值内存并返回指针,适用于所有类型;make专为[]T、map[K]V、chan T服务,返回已初始化的可用值——二者不能互换,选错会panic。
直接说结论:new 只分配零值内存并返回指针,适用于所有类型;make 专为 []t、map[k]v、chan t 服务,返回已初始化的可用值——二者不能互换,选错会 panic。
为什么 new([]int) 会 panic,而 make([]int, 5) 不会
因为 new([]int) 返回的是 *[]int,解引用后仍是 nil 切片:底层数组未分配,len 和 cap 都是 0,无法下标访问或 append。而 make([]int, 5) 直接返回一个长度为 5、容量为 5 的切片,底层数组已就位。
-
new([]int)→ 得到*[]int,*p是[]int(nil),len(*p) == 0,append(*p, 1)panic -
make([]int, 5)→ 得到[]int,len(s) == 5,s[0] = 1合法 - 同理:
new(map[string]int) 返回*map[string]int,(*m)["k"] = v直接 panic;make(map[string]int)返回非 nil map,可立即写入
哪些类型只能用 make,哪些可以用 new
make 的类型限制是硬性编译期约束:只接受 []T、map[K]V、chan T。传 int、struct{}、*int 都会报错 cannot make type ...。而 new 接受任意类型,包括 []int、map[string]int(但毫无意义)。
- 必须用
make:所有 slice/map/chan 实例创建场景,比如初始化空 map 供后续填充、预分配切片容量避免扩容、创建带缓冲 channel - 可用
new:需要一个非 nil 的结构体指针且字段全为零值时(如new(Handler)),但更惯用写法是&Handler{} - 慎用
new:基础类型指针(如new(int)),多数情况不如直接声明变量或用字面量;它强制堆分配,可能增加 GC 压力
参数和性能差异:cap、hint、buffer 怎么传才不浪费
make 的参数含义因类型而异,传错既不生效又误导人:
- 切片:
make([]int, len, cap)—— 第三个参数是容量,省略时等价于cap == len;预设cap能避免多次底层数组复制,比如make([]int, 0, 100)追加 100 元素无 realloc - map:
make(map[int]string, hint)—— 第二个参数是哈希桶数量提示,Go 会向上取整到 2 的幂(如传 10 → 实际分配 16 个 bucket),不是精确容量,传太大纯属浪费内存 - channel:
make(chan int, buffer)—— 第二个参数是缓冲区长度,传 0 或不传即为无缓冲 channel;缓冲区过大易掩盖同步设计问题 -
new没有参数可调,只接收一个类型,返回指针;它的“性能”只体现在是否触发逃逸——go tool compile -gcflags="-m" file.go可验证
真正容易被忽略的是:结构体字段含 slice/map/chan 时,new(MyStruct) 不会初始化这些字段,它们仍是 nil;必须显式对每个字段调用 make,或者改用字面量 &MyStruct{items: make([]int, 0, 16)}。
立即学习“go语言免费学习笔记(深入)”;


















