

Go 语言在即将到来的 1.26 版本 中,对内建函数 new 引入了一个有趣的小修改:从此 new() 不仅能接受类型,还可以接受表达式。这个变化虽小,却能让代码写得更优雅。
本文将以浅显易懂的方式,介绍这个新特性、它背后的原理、使用示例,以及可能带来的影响与限制。
在 Go 1.25 及以前版本,new 只能写成:
p := new(int) // 返回 *int,值为 0
而新版本中,new 可以写成:
p := new(42) // 返回 *int,值为 42
——对表达式 expr 求值,并把其结果作为初始值写入新分配对象,然后返回指向该对象的指针。(antonz.org)
换句话说:
new(T):分配一个零值的 T,返回 *T。new(expr):先计算 expr 得到一个值 v(类型为 T),再分配一个类型为 T 的变量,其初始值为 v,返回 *T。(antonz.org)
https://go.dev/play/p/cc0aOdN_tJ4?v=gotip
p1 := new(42)
fmt.Println(*p1) // 输出 42
p2 := new("hello")
fmt.Println(*p2) // 输出 "hello"
p := new([]int{1, 2, 3})
fmt.Println(*p) // 输出 [1 2 3]
type Person struct { Name string }
p2 := new(Person{Name: "Alice"})
fmt.Println(*p2) // 输出 {Alice}
f := func() string { return "Go" }
p := new(f())
fmt.Println(*p) // 输出 "Go"
注:new(nil) 依然会编译错误,不能传入 nil 表达式。(antonz.org)
减少样板代码 在以前,如果你想把一个简单值转成指针,通常要先声明一个变量再取地址:
v := 42
p := &v
而现在可以直接写 p := new(42),更简洁。
统一与一致性
允许 new(expr) 后,new(...) 的用途更加灵活统一:既可表示“按类型分配(零值)”,也可表示“按表达式赋初值再分配”。
提升代码可读性
某些场景下表达式本身就很直观,直接写 new(expr) 比先定义再取指针的写法更直观、更少中间变量。
expr 必须可以在编译时确定其类型(或者是常量表达式、明确类型表达式)。nil、接口类型、或者某些复杂类型表达式,可能还需要语言规范与实现进一步明确。Go 1.26 引入的 new(expr) 虽然是一个“小改动”,却能带来不少语法上的简洁和一致性提升。对于日常的简单值或字面量想要转指针的场景,它尤为便利。