new返回*T类型指针,指向零值内存,永不为nil;但解引用后可能为nil(如new([]int)),需用make或字面量初始化后再取地址;仅适用于泛型、反射及底层零值分配场景。

new 返回的就是指针,不需要“配合”——它本身干的就是这件事:分配零值内存,返回指向它的指针。
new 的返回值类型永远是 *T
你写 new(int),得到的是 *int;写 new(string),得到的是 *string;写 new(MyStruct),得到的是 *MyStruct。它不返回值,只返回指针。
- 误以为
new返回值再取地址(比如&new(int))会编译失败:cannot take address of new(int) - 误把返回值当普通变量用,比如
var x = new(int); fmt.Println(x + 1)会报错:invalid operation: x + 1 (mismatched types *int and int) - 解引用前必须确认指针非 nil —— 但
new返回的指针本身**永远不会是 nil**,只是它指向的值可能是零值(比如new([]int)指向的是nil切片)
new([]int)、new(map[string]int 这类引用类型要特别小心
它们返回的指针本身合法,但解引用后是 nil,不能直接操作:
-
slicePtr := new([]int); append(*slicePtr, 1)→ panic:append to nil slice -
mapPtr := new(map[string]int); (*mapPtr)["k"] = 1→ panic:assignment to entry in nil map - 正确做法是:先
make出值,再取地址,例如s := make([]int, 0); ptr := &s - 或者直接用字面量初始化:
m := map[string]int{"a": 1}; ptr := &m
什么时候该用 new,而不是 &T{} 或 make
日常构造对象,&T{} 和 make 更直观、更安全。new 的合理使用场景非常窄:
立即学习“go语言免费学习笔记(深入)”;
- 泛型函数中,类型参数
T不确定是否可字面量化(比如T可能是int、struct{}或未导出类型),只能靠new(T)获得零值指针 - 反射中需要
reflect.New,它底层调用的就是new,用于动态分配指定类型的零值内存 - 极少数底层代码(如 runtime 或内存分析工具)需显式控制零值分配路径,且不希望触发逃逸分析的额外逻辑
- 不要为“统一风格”而用
new(MyStruct),它不表达字段意图,也不做任何初始化,容易遗漏赋值
真正容易被忽略的是:new 只管内存和零值,不管业务逻辑。你拿到 *http.Client 后,字段全是 nil,直接调 Do 就 panic —— 它不是构造函数,也不是初始化入口。


















