new分配零值内存并返回指针,不创建对象、不调用构造逻辑、不支持传参;如new(int)返回int(值为0),new([]string)返回[]string(值为nil)。

Go 里的 new 函数到底分配什么?
new 不创建对象,只分配零值内存并返回指针。它不调用任何构造逻辑,也不支持传参——哪怕类型有字段、有方法,new 也只管“划一块地,填满零值,给你地址”。比如 new(int) 返回 *int,值是 0;new([]string) 返回 *[]string,值是 nil。
常见误用是以为 new 能初始化结构体字段或触发自定义逻辑,结果发现字段全是零值、没做任何校验、也没执行初始化函数。
-
new(T)要求T是具体类型(不能是接口、不能是未定义类型别名) - 返回的是
*T,不是T;如果误当成值使用,会编译报错:invalid indirect of ... (type T) - 对 slice、map、chan 类型用
new得到的是nil指针,后续直接append或make会 panic
new 和 make 到底怎么选?
简单记:只有 map、slice、chan 这三种引用类型必须用 make 初始化;其他类型(包括 struct、array、指针自身)可用 new,但多数时候更推荐字面量 + 取地址。
make 返回的是值(如 []int),new 返回的是指针(如 *[]int)。二者语义完全不同:
-
make([]int, 5)→ 分配长度为 5 的底层数组,返回可直接使用的 slice 值 -
new([]int)→ 分配一个[]int类型的零值(即nil),返回*[]int,你得自己解引用再赋值才能用 - struct 推荐写法:
&MyStruct{Field: 42},比new(MyStruct)后逐个赋值更直观、更安全
什么时候真该用 new?
实际项目里 new 出现场景极少。唯一较合理的用途是:需要一个指向零值的指针,且类型无法用字面量表达(比如某些泛型约束下的抽象类型,或反射中动态构造)。
例如在泛型函数中,当类型参数 T 无法用 &T{} 构造(因为 T 可能不是结构体),又确实需要一个 *T 零值指针时,new(T) 是唯一选择:
func zeroPtr[T any]() *T {
return new(T)
}
但要注意:T 不能是 interface{},也不能是未定义的别名(如 type MyInt int 需要显式用 new(MyInt),不能靠推导)。
- 不要为“统一指针创建”而滥用
new,Go 习惯是按需构造,明确意图 - 用
new创建结构体后忘记初始化字段,容易导致空指针或逻辑错误(比如http.Client字段为nil时调用方法 panic) - 性能上无差异,但可读性差——看到
new(MyStruct)无法判断字段是否已就绪
常见错误:把 new 当成构造函数
最典型的坑是写 p := new(bytes.Buffer) 然后直接调用 p.WriteString —— 这没问题,因为 bytes.Buffer 的零值本身是合法的;但换成 p := new(http.Client) 再调用 p.Do(req) 就会 panic:因为 http.Client 的零值里 Transport 是 nil,而 Do 方法内部会解引用它。
- 标准库类型大多不保证零值完全可用,务必查文档(比如
sync.Mutex零值可用,http.Client零值不可直接用) - 自定义类型若依赖字段非零(如含
sync.Once、io.ReadCloser等),绝不能靠new初始化 - 静态分析工具(如
staticcheck)会警告new(T)后未初始化关键字段,这类警告别忽略
new 语法,而是判断某个类型在零值下是否可安全使用——这得看它的文档、源码,甚至运行时行为。别假设“指针有了,就能用”。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











