Go中nil指针解引用会panic,表现为“invalid memory address or nil pointer dereference”;必须在解引用(*p、p.field、p.Method())前显式判nil,而p==nil等比较操作是安全的。

Go 里没有“空指针异常”这个概念
Go 不会抛出类似 Java 的 NullPointerException 或 Python 的 AttributeError。当你对一个 nil 指针解引用(比如 *p),程序会直接 panic,错误信息通常是 panic: runtime error: invalid memory address or nil pointer dereference。这不是“异常处理”的范畴,而是**必须在运行前规避的崩溃点**。
哪些操作会触发 nil 指针 panic
最常见的是对 nil 指针做解引用或方法调用。但要注意:不是所有操作都会 panic。
-
*p—— 如果p是*T类型且为nil,必然 panic -
p.field—— 如果p是*struct{}且为nil,panic -
p.Method()—— 如果Method的接收者是值类型(func (t T) Method()),则调用前会隐式解引用*p→ panic;如果是指针接收者(func (t *T) Method()),则允许nil调用(只要方法内部不访问t字段) -
p == nil、p != nil—— 安全,推荐用于前置检查
安全使用指针的实操习惯
Go 的哲学是“显式检查优于依赖 recover”。别指望用 defer/recover 捕获 nil panic —— 它不可靠、难调试、掩盖设计缺陷。
- 函数入参为指针时,文档或注释明确是否接受
nil;若不接受,开头加if p == nil { panic("p must not be nil") } - 从 map、slice、channel 或函数返回获取指针时,先判空再解引用:
if p != nil { use(*p) } - 初始化结构体字段为指针时,避免裸写
&T{},优先用工厂函数封装逻辑和默认值 - 用
sync.Pool复用指针对象时,Get()返回值必须检查是否为nil(Pool 可能返回 nil)
一个典型易错场景:map 中存储指针
很多人误以为 m[key] 对 map 返回指针时“天然非 nil”,其实不然:
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
立即学习“go语言免费学习笔记(深入)”;
type User struct{ Name string }
m := make(map[string]*User)
u := m["missing"] // u 是 *User 类型,值为 nil
fmt.Println(*u) // panic: invalid memory address
正确做法是:
- 用双赋值判断 key 是否存在:
if u, ok := m["missing"]; ok { fmt.Println(u.Name) } - 或统一用零值兜底:
u := m["missing"]; if u == nil { u = &User{Name: "default"} }
nil 指针本身不是 bug,对 nil 解引用才是。关键不在“怎么 catch”,而在“怎么让解引用前一定有值”。

















