跳转到主内容
极星编程网:以代码为星,赴技术山海!

如何在Golang中判断指针是否为空 Go语言安全解引用实践

判断 nil 指针的正确写法是 if p == nil,不可用 if !p(语法错误)或其它变体;解引用前必须显式检查,尤其注意接口非空不等于指针非空、嵌套字段需逐级判空、切片/map 中指针元素需单独检查。 判断
nil
指针的正确写法 Go 中指针变量未初始化时默认是
nil
,但直接解引用
nil
会导致 panic:"
invalid memory address or nil pointer dereference
"。安全的第一步永远是显式比较:
if p == nil
—— 不要用
if !p
(语法错误),也不能用
if p != nil
以外的任何变体去“取巧”。 常见错误现象:在结构体字段、函数返回值、map 查找结果中拿到一个指针后,没检查就直接访问
p.Field
,运行时报 panic。
nil
是预声明标识符,类型为
nil
的指针与任意具体指针类型(如
*string
、
*User
)可比较,无需类型断言 接口变量里存了
*T
值,但该指针本身是
nil
,此时接口变量不为
nil
—— 这是高频踩坑点:接口非空 ≠ 指针非空 切片、map、channel 的零值也是
nil
,但它们不是指针类型,不能和指针混为一谈
if p == nil
之后怎么安全解引用 检查通过后,解引用本身没有额外技巧,但要注意上下文是否允许修改原值。比如函数参数传入
*int
,你解引用后赋值
*p = 42
是合法的;但如果该指针来自只读场景(如从 JSON 解析出的嵌套结构体字段),盲目修改可能破坏数据一致性。 使用场景典型包括:HTTP handler 中解析请求体得到
*User
,数据库查询返回
*Order
,或配置项允许字段为空时用指针表示缺失。 立即学习 “ go语言免费学习笔记(深入) ”; 不要在一行里连写
if p != nil { doSomething(*p) }
后紧接着
*p = ...
—— 即使前面判了非空,中间若被并发写入或重置,仍可能 panic(虽少见,但真实存在) 如果逻辑需要多次解引用,建议提前赋值:
val := *p
,后续用
val
,避免重复解引用开销(微小但确定) 对
interface{}
类型变量,先类型断言再判空:
if u, ok := v.(*User); ok && u != nil
结构体字段为指针时的空值处理惯用法 当结构体字段定义为
*string
或
*time.Time
,意味着该字段可选。这时不能假设它有值,尤其在 JSON 反序列化后:空 JSON 字段会得到
nil
指针,而非零值。 go语言参考手册 中文CHM版 Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译 下载 性能影响很小,但兼容性上要注意:gRPC、OpenAPI 等协议常将 optional 字段映射为指针,而前端传
null
就对应后端
nil
。 别用
fmt.Sprintf("%v", p)
判断是否为空 ——
nil
指针打印出来是
,但字符串匹配不可靠,且有额外分配 给指针字段提供 “Get” 方法是常见做法:
func (u *User) Name() string { if u.Name == nil { return "" } else { return *u.Name } }
数据库 ORM(如 GORM)对零值字段默认跳过更新,但如果字段是
*string
且设为
nil
,会明确更新为 NULL —— 这和普通字段行为不同,需留意 容易被忽略的边界:数组、切片、map 中的指针元素 数组或切片元素类型为指针(如
[]*User
),其每个元素都可能是
nil
。遍历时若不做检查,
for _, u := range users { fmt.Println(u.Name) }
会在某个
u == nil
时 panic。 这不是 Go 的 bug,而是设计使然:指针就是可以为空的引用,语言不替你做隐式空值保护。 循环内必须单独检查:
if u != nil { fmt.Println(u.Name) }
map 的 value 是指针时同理:
v, ok := m[key]; if ok && v != nil
——
ok
只说明 key 存在,不保证 value 非空 用
sync.Map
存指针?同样适用:value 是
interface{}
,取出后要先断言再判空 最麻烦的不是写
== nil
,而是忘记在深层嵌套里检查——比如
req.User.Profile.AvatarURL
,其中任意一级是
nil
都会崩。这时候要么分步判空,要么用工具生成带空检查的访问函数,别硬扛。

相关文章