如何理解Golang中nil指针的含义_Golang空指针常见问题解析
技术百科
P粉602998670
发布时间:2026-01-27
浏览: 次 nil指针是合法零值,解引用才panic;interface含nil指针时不等于nil;访问嵌套指针需逐层判空或封装安全访问器。
nil 指针不是“空对象”,而是未指向任何内存地址的指针值——它本身合法,解引用才 panic。
为什么 var p *int 不报错,但 *p 会崩溃?
Go 中 nil 是指针类型的零值,声明即得,不分配内存。它和 C 的 NULL 类似,但更严格:你不能对它做任何读写操作(*p、p.Method()、p.Field),否则立刻触发 panic: runtime error: invalid memory address or nil pointer dereference。
-
nil指针本身可安全比较:p == nil是合法且推荐的第一步 - 结构体指针接收者方法里,
u *User可能为nil,所以func (u *User) GetName() string内部仍需先判if u == nil - 函数返回指针时,若失败应返回
nil, err,而不是只返回nil—— 调用方必须先检查err != nil,再用指针
接口里藏了个 nil 指针,为什么 i == nil 却是 false?
这是最常踩的坑:interface{} 是“类型 + 值”的组合。只要动态类型存在(哪怕值是 nil),接口变量就不等于 nil。
var p *string = nil
var i interface{} = p
fmt.Println(i == nil) // false —— 类型是 *string,值是 nil
fmt.Println(p == nil) // true
- 错误写法:
if err != nil { return }看似稳妥,但如果err是*MyError类型且为nil,赋给error接口后,err != nil仍
为
true,但err.Error()会 panic - 正确做法:自定义错误类型时,确保
Error()方法不依赖任何可能为nil的字段;返回错误统一用return nil,而非return (*MyError)(nil) - 调试时可用
reflect.ValueOf(i).IsNil()辅助判断,但生产代码应从设计上避免把裸nil指针塞进接口
结构体字段是 *string,怎么安全取值?
嵌套指针字段天然易空,不能靠“应该有”来假设。比如 User{Name: nil} 是完全合法的状态。
- 访问前逐层判空:
if u != nil && u.Name != nil { fmt.Println(*u.Name) } - 封装安全访问器,避免重复逻辑:
func (u *User) SafeName() string { if u == nil || u.Name == nil { return "" } return *u.Name } - 构造时明确语义:用
NewUser(name string)强制初始化关键字段,或文档注明某字段“允许为nil”,让调用方知情 - 别用
json.Unmarshal直接填入含指针字段的结构体后就直接解引用——JSON 中缺失字段会导致对应指针为nil
真正危险的从来不是 nil 本身,而是你以为它“不会是 nil”的那个瞬间。HTTP 客户端返回 *http.Response、数据库查询返回 *User、JSON 解析生成 *Config……这些地方,nil 出现得既合理又隐蔽。养成“声明即检查、接收即防御、返回即担保”的习惯,比记住所有规则更管用。
# 这是
# 常见问题
# 却是
# 能为
# 自定义
# 你不
# 而非
# 能对
# 就不
# 再用
# http
# js
# json
# go
# golang
# Error
# 对象
# String
# if
# int
# 指针
# 接口
# nil
# 数据库
# 报错
# 为什么
# pointer
# Interface
# var
# NULL
# 封装
# 结构体
# 指针类型
# 空指针
# 访问器
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win11怎么开启上帝模式_创建Windows 1
- Linux如何安装Golang环境_Linux下G
- Win11怎么关闭触控板_Win11笔记本禁用触摸
- php中$this和::能混用吗_对象与静态作用域
- 如何在 Go 中正确反序列化 XML 多节点数组(
- Win11怎么关闭透明效果_Windows11个性
- Win11怎么更改电脑密码_Windows 11修
- Win11怎么修复系统文件_使用sfc命令修复Wi
- 如何使用Golang实现微服务状态监控_Golan
- Python如何创建带属性的XML节点
- c# 在ASP.NET Core中管理和取消后台任
- 如何使用Golang处理静态文件缓存_提高页面加载
- Python lxml的etree和Element
- Win11怎么关闭贴靠布局_Win11禁用窗口最大
- 如何在 Windows 11 中使用 AlomWa
- Win11资源管理器卡顿怎么办 Win11文件资源
- c++如何用AFL++进行模糊测试 c++ Fuz
- Win11怎样安装剪映专业版_Win11安装剪映教
- Win11系统更新后黑屏怎么办 Win11更新黑屏
- c++怎么处理多线程死锁_c++ lock_gua
- Win11怎么更改输入法顺序_Win11调整语言首
- 如何在Golang中处理URL参数_Golang
- c++如何获取map中所有的键_C++遍历键值对提
- Python装饰器复用技巧_通用能力解析【教程】
- php8.4新语法match怎么用_php8.4m
- Windows10如何更改任务栏高度_Win10解
- Win11怎么设置单手模式_Win11触控键盘布局
- Win11怎样安装微信开发者工具_Win11安装开
- Win11怎么禁用键盘自带键盘_Win11笔记本禁
- Win11怎么更改文件夹图标_自定义Win11文件
- windows如何禁用驱动程序强制签名_windo
- Win11怎么激活Windows10_Win11激
- GML (Geography Markup Lan
- Python异步网络编程_aiohttp说明【指导
- 如何使用Golang管理模块版本_Golanggo
- Win11如何更改用户账户文件夹名称 Win11修
- Python文件管理规范_工程实践说明【指导】
- PHP 中 require() 语句返回值的用法详
- 如何自定义Windows终端的默认配置文件?(Po
- Python实现图数据库操作_Neo4j核心CRU
- Linux怎么设置磁盘配额_Linux系统Quot
- Windows10如何删除恢复分区_Win10 D
- Win11局域网共享怎么设置 Win11文件夹网络
- Windows蓝屏错误0x0000002C怎么解决
- php增删改查需要哪些扩展_开启mysqli或pd
- Win11怎么关闭搜索历史_Win11清除设备上的
- Win11关机快捷键是什么_Win11快速关机方法
- php和redis连接超时怎么办_phpredis
- php修改数据怎么改富文本_update更新htm
- Win11讲述人怎么关闭_Win11误触开启语音朗


QQ客服