new()分配零值内存并返回*T指针,make()专为slice/map/chan初始化并返回值类型;混用导致编译失败或运行时panic。

new() 和 make() 都返回指针,但干的事完全不同
别被返回值迷惑:new() 只做一件事——分配零值内存并返回指向它的指针;make() 专为 slice、map、chan 服务,它不仅分配内存,还完成初始化(比如 slice 的 len 和 cap、map 的底层哈希表结构)。混用会直接编译失败。
-
new([]int)返回*[]int,但这个 slice 是 nil,不能直接append或取下标 -
make([]int, 0)返回[]int,可立即使用,底层已准备好可增长的数组 - 对 struct、int、string 等类型,只能用
new()(或字面量),make()会报错:cannot make type struct {...}
什么时候必须用 make()?看类型是否内置支持
Go 编译器硬编码了 make() 的合法类型:仅 slice、map、chan。其他任何类型传给 make() 都会触发编译错误,比如 make([]*int, 5) 合法(生成长度为 5 的 slice),但 make(*int, 5) 不合法(*int 不是三者之一)。
- 初始化空 map:用
make(map[string]int),不是new(map[string]int)(后者返回*map[string]int,且该 map 本身仍是 nil) - 创建带缓冲的 channel:
make(chan int, 10)——new(chan int)语法都不通过 - 想预分配 slice 容量?
make([]byte, 0, 1024)比先new()再强制转换安全得多
new(T) 返回 *T,但 T 不能是 interface 或未定义类型
new() 要求参数是具体类型,且必须已声明。常见翻车点:把接口变量当类型传,或者用未加 type 声明的复合字面量。
-
new(io.Reader)❌ 编译错误:cannot use io.Reader (type interface {}) as type T -
new(struct{ x int })✅ 合法,但返回的是*struct{ x int },字段值为零 - 更自然的写法其实是字面量:
&struct{ x int }{x: 1},比new()更直观 - 对自定义类型,
type MyInt int; new(MyInt)✅,但new(int)也行,只是通常没必要
性能差异小,但语义错误会导致 panic
分配开销本身微乎其微,真正要命的是用错后运行时崩溃。比如对 nil map 写入、对 nil slice 调 append,都会 panic:assignment to entry in nil map 或 panic: runtime error: cannot append to nil slice。
立即学习“go语言免费学习笔记(深入)”;
- 查日志看到这类 panic,第一反应不是“内存不够”,而是检查 map/slice 初始化是否漏了
make() - 静态分析工具(如
go vet)不会捕获new(map[T]V)这种写法,但它在运行时必然出事 - 如果函数接收指针参数并打算修改内部 map/slice,调用方必须确保传入的是
make()初始化的值,而非new()出来的零值指针
最易忽略的一点:make() 返回的是值类型(如 []int),而 new() 返回的是指针类型(如 *[]int)。类型系统不帮你自动解引用,少一个星号就可能让后续逻辑完全走偏。










