判断 nil 指针的正确写法是 if p == nil,不可用 if !p(语法错误)或其它变体;解引用前必须显式检查,尤其注意接口非空不等于指针非空、嵌套字段需逐级判空、切片/map 中指针元素需单独检查。
判断
指针的正确写法
Go 中指针变量未初始化时默认是
,但直接解引用
会导致 panic:"
"。安全的第一步永远是显式比较:
—— 不要用
(语法错误),也不能用
以外的任何变体去“取巧”。
常见错误现象:在结构体字段、函数返回值、map 查找结果中拿到一个指针后,没检查就直接访问
,运行时报 panic。
是预声明标识符,类型为
的指针与任意具体指针类型(如
、
)可比较,无需类型断言
接口变量里存了
值,但该指针本身是
,此时接口变量不为
—— 这是高频踩坑点:接口非空 ≠ 指针非空
切片、map、channel 的零值也是
,但它们不是指针类型,不能和指针混为一谈
之后怎么安全解引用
检查通过后,解引用本身没有额外技巧,但要注意上下文是否允许修改原值。比如函数参数传入
,你解引用后赋值
是合法的;但如果该指针来自只读场景(如从 JSON 解析出的嵌套结构体字段),盲目修改可能破坏数据一致性。
使用场景典型包括:HTTP handler 中解析请求体得到
,数据库查询返回
,或配置项允许字段为空时用指针表示缺失。
立即学习
“
go语言免费学习笔记(深入)
”;
不要在一行里连写
后紧接着
—— 即使前面判了非空,中间若被并发写入或重置,仍可能 panic(虽少见,但真实存在)
如果逻辑需要多次解引用,建议提前赋值:
,后续用
,避免重复解引用开销(微小但确定)
对
类型变量,先类型断言再判空:
结构体字段为指针时的空值处理惯用法
当结构体字段定义为
或
,意味着该字段可选。这时不能假设它有值,尤其在 JSON 反序列化后:空 JSON 字段会得到
指针,而非零值。
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 字段映射为指针,而前端传
就对应后端
。
别用
判断是否为空 ——
指针打印出来是
,但字符串匹配不可靠,且有额外分配
给指针字段提供 “Get” 方法是常见做法:
数据库 ORM(如 GORM)对零值字段默认跳过更新,但如果字段是
且设为
,会明确更新为 NULL —— 这和普通字段行为不同,需留意
容易被忽略的边界:数组、切片、map 中的指针元素
数组或切片元素类型为指针(如
),其每个元素都可能是
。遍历时若不做检查,
会在某个
时 panic。
这不是 Go 的 bug,而是设计使然:指针就是可以为空的引用,语言不替你做隐式空值保护。
循环内必须单独检查:
map 的 value 是指针时同理:
——
只说明 key 存在,不保证 value 非空
用
存指针?同样适用:value 是
,取出后要先断言再判空
最麻烦的不是写
,而是忘记在深层嵌套里检查——比如
,其中任意一级是
都会崩。这时候要么分步判空,要么用工具生成带空检查的访问函数,别硬扛。
nilnilnilinvalid memory address or nil pointer dereferenceif p == nilif !pif p != nilp.Fieldnilnil*string*User*Tnilnilnilif p == nil*int*p = 42*User*Orderif p != nil { doSomething(*p) }*p = ...val := *pvalinterface{}if u, ok := v.(*User); ok && u != nil*string*time.Timenilnullnilfmt.Sprintf("%v", p)nilfunc (u *User) Name() string { if u.Name == nil { return "" } else { return *u.Name } }*stringnil[]*Usernilfor _, u := range users { fmt.Println(u.Name) }u == nilif u != nil { fmt.Println(u.Name) }v, ok := m[key]; if ok && v != niloksync.Mapinterface{}== nilreq.User.Profile.AvatarURLnil