只有 slice、map、chan 三种类型可用 make;其他类型(如 struct、指针类型)用 make 会编译失败;new 返回指向零值的指针,make 返回已初始化的值。

make 和 new 完全不互换,用错会直接 panic 或导致运行时 nil 指针解引用——不是“风格差异”,而是类型系统强制约束。
哪些类型只能用 make?
只有 slice、map、chan 这三种内置引用类型能用 make。其他任何类型(包括 struct、[]int 的指针、*map[string]int)传给 make 都会编译失败。
-
make([]int, 5)✅ 返回一个长度为 5、元素全为 0 的切片值 -
make(map[string]int)✅ 返回一个可直接m["k"] = 1赋值的 map 值 -
make(chan int, 10)✅ 返回带缓冲区的 channel 值 -
make(struct{X int})❌ 编译错误:cannot make type struct { X int } -
make(*[]int)❌ 编译错误:cannot make type *[]int
new 返回指针,make 返回值本身
new(T) 总是返回 *T,且所指内存内容为 T 的零值;make(T, ...) 只接受那三种类型,返回的是 T 类型的值(不是指针),且已就绪可用。
-
p := new(int)→p是*int,*p == 0 -
s := make([]int, 3)→s是[]int,len(s) == 3,可直接s[0] = 1 -
m := new(map[string]int❌ 不合法:虽然map[string]int是类型,但new允许它,返回的是*map[string]int,即一个指向 nil map 的指针,*m仍是 nil,后续(*m)["k"] = 1会 panic
误用 new 初始化 map/slice/chan 的典型崩溃场景
写 var m = new(map[string]int 或 m := new(map[string]int) 看似语法合法,但实际得到的是一个指向 nil map 的指针。解引用后仍是 nil,无法使用。
立即学习“go语言免费学习笔记(深入)”;
-
m := new(map[string]int→m类型是*map[string]int,*m == nil -
(*m)["x"] = 1→ panic: assignment to entry in nil map - 正确做法只有两种:
m := make(map[string]int)(要值),或m := &map[string]int{}(先 make 再取地址,极少用) - 同理,
s := new([]int)得到的是*[]int,*s == nil,对*s调用append会 panic
结构体和自定义类型该用哪个?
结构体既不能用 make,也不必非用 new。优先用字面量;需要指针时,&MyStruct{} 比 new(MyStruct) 更直观,且能设初始字段值。
-
s := MyStruct{Name: "a"}→ 值类型,栈上分配 -
s := &MyStruct{Name: "a"}→ 指针,等价于new(MyStruct)+ 字段赋值,但更清晰 -
new(MyStruct)→ 所有字段都是零值,无法指定初始值,语义弱 -
make(MyStruct)→ 编译报错:cannot make type MyStruct
真正容易被忽略的是:你写的变量是否「需要被外部修改」或「内部含需初始化的引用字段」——这时候往往得自己写 NewXXX() 函数,而不是依赖 new 或 make。


















