new返回*T类型零值指针,make返回T类型已初始化引用值;slice/map/chan必须用make,结构体用new或&T{},不可用make。

new 和 make 都返回指针,但类型完全不同
new 返回的是指向零值的指针,类型为 *T;make 返回的是引用类型本身(非指针),类型为 T(如 []int、map[string]int、chan int)。试图用 make 初始化结构体或基本类型会编译失败。
-
new(int)→ 返回*int,值为nil指针指向的0 -
make([]int, 5)→ 返回[]int,底层数组已分配,长度为 5 -
make(struct{a int})→ 编译错误:cannot make type struct { a int } -
new([]int)→ 返回*[]int,但内部 slice header 仍为零值(nil),不能直接 append
slice、map、chan 必须用 make,不能用 new
这三类类型在 Go 中是引用类型,底层由 header 结构(含指针、长度、容量等)描述。new 只分配 header 内存并清零,得到的是一个 nil 值;而 make 不仅分配 header,还初始化其字段,并为底层数组/哈希表/队列分配实际内存。
-
var m map[string]int = new(map[string]int)→m是*map[string]int,解引用后仍是nil,for range m或m["k"] = 1panic -
m := make(map[string]int)→m是可用的空 map,可安全读写 -
s := new([]byte)→ 得到*[]byte,*s == nil;s := make([]byte, 0)→ 得到可 append 的空 slice
new 适合快速获得零值指针,尤其用于结构体
当需要一个指向已初始化结构体的指针时,new(T) 等价于 &T{},但更简洁。它不调用任何构造逻辑,也不支持字段初始化。
type User struct {
ID int
Name string
}
u1 := new(User) // 等价于 &User{}
u2 := &User{} // 同上,语义更直观
u3 := &User{ID: 1} // ❌ new 无法做到字段赋值,只能靠 &T{...}
-
new(User)安全、无副作用,适合初始化大型结构体指针 - 若需设置初始字段,必须用
&User{...},不能依赖new - 注意:对结构体使用
make是语法错误,Go 不允许
性能与逃逸:new 和 make 都可能触发堆分配
是否分配在堆上,取决于编译器逃逸分析,和用 new 还是 make 无直接关系。但行为模式会影响判断:
立即学习“go语言免费学习笔记(深入)”;
- 小 slice(如
make([]int, 4))可能被分配在栈上(如果未逃逸) -
new(int)分配单个整数,几乎总在栈上,除非该指针被返回或存储到全局变量 -
make(map[int]int, 1000)通常逃逸到堆,因为 map 底层哈希表结构复杂且需动态增长 - 用
go tool compile -gcflags="-m" main.go可验证具体分配位置
别默认认为 new 更“轻量”——它只是语义不同,不是性能优化手段。










