不能写 new(int){5} 或 &5,因为 int 是标量类型,不支持复合字面量初始化;而字面量 5 没有内存地址,Go 禁止对其取地址,这是语言强制的安全限制。

为什么不能写 new(int){5} 或 &5
Go 编译器会直接报错,因为 int 是标量类型,不是复合类型(如 struct、map),不支持用 {} 初始化;而字面量 5 没有内存地址,Go 禁止对其取地址——这是语言层面的强制安全限制。
常见错误现象包括:
-
cannot take the address of 5(试图&5) -
cannot use composite literal new(int) as type *int(误用new(int){5}) -
undefined: x(在短声明中写x, y := 5, &x,右侧x尚未完成声明)
&x 是最常用且推荐的初始化方式
只要 x 是可寻址的变量(命名变量、结构体字段、切片元素等),&x 就是安全、高效、类型推导清晰的初始化手段。
- 函数内优先用短变量声明:
x := 42; p := &x,p自动为*int - 若需显式类型或延迟赋值,可用:
var x int = 42; var p *int = &x - 注意:不能对函数返回值直接取地址,除非该返回值本身是地址(如
&slice[0]合法,但&someFunc()非法)
什么时候该用 new(T)
new(T) 只做一件事:分配零值内存并返回其地址。它不接受初始化参数,也不支持字段赋值语法,适用于明确需要一个“空但非 nil”指针的场景。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
立即学习“go语言免费学习笔记(深入)”;
- 结构体字段初始化:
type Config struct{ Timeout *int }; cfg := &Config{Timeout: new(int)},此时*cfg.Timeout == 0 - 函数返回零值指针:
func newCounter() *int { return new(int) },调用方后续可安全写*p = 1 - 对比
&T{}:后者可用于结构体并支持字段初始化,new(T)更适合纯标量或你只想确保指针非 nil 但暂不关心初始值的情况
解引用前必须检查是否为 nil
对 nil 指针执行 *p 会触发 panic: invalid memory address or nil pointer dereference,这在函数参数、配置解析、API 响应字段中极易发生。
- 安全写法:
if p != nil { fmt.Println(*p) } - 避免隐式解引用:日志打印时别直接写
fmt.Printf("%d", *p),应先判空或用fmt.Printf("%v", p)打印指针本身 - 第三方库返回的指针(如
json.Unmarshal解析到*string字段)可能为nil,务必检查再使用
真正容易被忽略的是:可寻址性(addressability)不是看“有没有值”,而是看“有没有稳定内存位置”。局部变量、全局变量、切片元素、结构体字段都满足;字面量、常量、函数返回的临时值都不满足。理解这一点,才能避开 90% 的取地址编译错误。

















