new只分配指定类型的零值内存并返回指针,不创建实例、不调用构造逻辑;对slice/map/chan返回nil指针,需make初始化;泛型中获取零值指针是其主要适用场景。

Go 中 New 函数到底分配什么
New 不创建结构体实例,也不调用构造逻辑,它只做一件事:申请一块指定类型的零值内存,并返回指向它的指针。比如 New(int) 返回 *int,其值是 0;New([]string) 返回 *[]string,其值是 nil(不是空切片,是 nil 指针)。
常见错误现象:
– 对 *[]T 直接 append 报 panic: "invalid memory address or nil pointer dereference"
– 误以为 New(StructType) 会初始化字段为非零默认值(比如 time.Time 字段仍是零时间)
-
New返回的永远是指针,类型是*T,不是T - 它不调用任何方法,不触发任何初始化逻辑(如 struct 的字段未被显式赋值,就保持零值)
- 对 slice、map、chan 等引用类型,
New返回的是nil指针,不能直接使用,必须后续用make或字面量赋值
什么时候该用 New,什么时候该用 &T{} 或 make
绝大多数情况,你不需要 New。它适合的场景非常窄:当你明确需要一个指向零值的指针,且类型不含引用字段,或你准备自己处理后续初始化。
使用场景对比:
立即学习“go语言免费学习笔记(深入)”;
- 想获得一个可修改的、带零值的结构体指针?直接写
&MyStruct{}—— 更直观,且能同时设置部分字段:&MyStruct{Field: 42} - 要初始化 slice/map/chan?必须用
make,New给你的是nil,没法 append 或 write - 泛型函数中需要统一获取某类型的零值指针?
New是少数合法手段(例如func NewPtr[T any]() *T { return new(T) })
性能影响几乎为零,但可读性上,&T{} 在大多数上下文中更贴近意图。
New 和 new(小写)关键字的区别
Go 里没有 new 关键字。这是个高频混淆点:有人在 Stack Overflow 上搜 “go new keyword”,结果发现根本不存在。唯一的 new 是内置函数 New(首字母大写),位于 builtin 包,无需导入。
错误现象:
– 写 new(int)(小写):编译报错 undefined: new
– 误以为它是类似 C++ 的操作符,试图重载或组合使用
- 只能用
New(T),且T必须是具体类型(不能是接口或未定义类型别名) - 不能传入表达式,比如
New(*int)合法,但New(int + 1)编译不过 - 它和
make一样是编译器内置函数,不是标准库函数,所以查文档要翻 builtin 包说明
容易被忽略的兼容性细节
New 的行为从 Go 1.0 起就没变过,但它在泛型代码中的表现容易埋坑。
- 如果泛型参数
T是 interface 类型,New(T)编译失败 —— 因为 interface 本身不是具体类型,无法分配内存 - 当
T是数组类型(如[3]int),New([3]int)返回*[3]int,这个指针可直接取地址、传递,但注意:它不是 slice,不能用len/cap以外的 slice 操作 - 在 cgo 场景下,
New(C.struct_xxx)是安全的,但若结构体含 Go 指针字段(比如*C.char),需确保生命周期管理得当,否则 GC 可能提前回收
真正复杂的地方不在语法,而在于:你是否清楚自己要的到底是“一个可寻址的零值”,还是“一个可用的初始化对象”。前者才轮到 New 出场;后者,基本都该换掉。










