new是运行时内存分配函数,返回指向零值的指针;它适用于所有具体类型,但不支持接口、未定义别名,对slice/map/chan无实际意义,且无法初始化字段。

new 不是声明,是运行时内存分配函数——它不声明变量,只分配零值内存并返回指针。
你写 var p *int 是声明;写 p := new(int) 是调用函数、申请堆(或栈)内存、初始化为 0、返回地址。两者语义完全不同。
new 能用于哪些类型?
- ✅ 所有具体类型:基本类型(
int、string)、结构体(struct{})、数组([3]int)、指针类型(*int) - ❌ 接口类型:
new(interface{})编译失败 - ❌ 未定义的类型别名:比如没声明
type MyInt int就直接new(MyInt),报错“undefined” - ⚠️ 切片 / map / chan:能用,但毫无意义
-
new([]int)返回*[]int,解引用后是nil,不能len、append、range - 同理,
new(map[string]int) 得到*map[string]int,解引用后仍是nil,直接赋值 panic
-
new(T) 和 &T{} 的实际差异
- 两者都返回
*T,字段/元素都是零值 - 但:
-
new(T)是纯分配 + 零值,无法同时设字段 -
&T{Field: "x"}支持字面量初始化,意图更清晰 - 若
T含嵌套指针字段(如Log *os.File),两者都只给该字段赋nil,不会自动new或open -
new在泛型中不可替代:func NewPtr[T any]() *T { return new(T) }—— 这是它唯一「非替代性」场景
-
容易 panic 的典型误用
- 对
new出来的 slice/map/chan 直接操作:s := new([]int) s = append(*s, 1) // panic: append to nil slice
- 忘记判空就解引用指针参数:
func process(p *string) { fmt.Println(*p) } // 若传 nil,直接 panic - 混淆
new(string)和未初始化的*string:-
new(string)→ 指向""的有效地址 -
var s *string→ 值为nil,不能解引用
-
真正难处理的不是语法,而是「零值指针是否可用」——比如 <em>sync.Mutex</em> 零值合法,http.Client 零值却不能直接用。这得看类型本身的设计,new 不保证这点。


















