Uber Go 出了个静态分析工具 NilAway,还挺实用!

大家好,我是煎鱼。

风水轮流转,Go 程序写多了。总是会这有点问题,那有点问题。问题积累久了就容易出点事件,甚至是事故。

这种时候大家往往会想着引入一些静态分析工具来解决这个问题。

NilAway 分析工具

最近 Uber 开发和开源了一个挺不错的静态分析工具 NilAway:

使用场景是:在 Go 程序编译时就能捕获 nil,达到帮助开发人员规避在生产中出现 nil panic 的问题。

官方认为其具备以下三个重要的特点,让其脱颖而出:

  1. 完全自动化:该分析工具只需要用户提供标准的 Go 代码就可以使用了。不需要其他任何额外的信息。
  2. 速度快:在设计上,NilAway 保持速度快且可扩展,目标是大型代码库也可以使用。在官方的性能测量中,启用 NilAway 时构建时间开销不到 5%。
  3. 很实用:它不能防止代码中所有可能的 nil panic,但能捕获我们在生产中观察到的大部分潜在 nil panic,从而使 NilAway 在实用性和构建时间开销之间保持良好的平衡。

安装

我们只需要在命令行执行如下命令安装:

shell 复制代码
$ go install go.uber.org/nilaway/cmd/nilaway@latest

nilaway 能够遍历扫描目录下的所有文件:

shell 复制代码
$ nilaway ./...

也可以扫描单独的文件:

go 复制代码
$ nilaway demo.go

注:本文安装 @latest 的原因,是因为写此文时 nilaway 还在积极开发阶段,暂时没有发布正式的版本。如果后续有正式版本,也可以指定相应版本号。

代码示例

案例一

看看如下的代码,是在什么场景下有问题:

go 复制代码
var p *P
if someCondition {
      p = &P{}
}
print(p.f) // nilness reports NO error here, but NilAway does.

在上述代码中,当 someCondition 变量值为 true 时,才会初始化结构体 P。如果 someCondition 变量为 false 时,就会出现空指针调用的 panic 问题。

NilAway 工具可以捕获这种错误并报告,会报告如下错误:

go 复制代码
go.uber.org/example.go:12:9: error: Potential nil panic detected. Observed nil flow from source to dereference point:
    -> go.uber.org/example.go:12:9: unassigned variable `p` accessed field `f`

如果我们增加 if p != nil 来做防御,报告的错误就会消失。

案例二

看看如下的代码,是为什么有问题:

go 复制代码
func foo() *int {
	return nil
}
func bar() {
	print(*foo())
}

func main() {
	// 煎鱼正在干点什么...
	bar() // nilness reports NO error here, but NilAway does.
}

函数 foo 返回了一个 nil 指针,该指针在函数 bar 中被直接解引用,导致每当调用函数 bar 时都会出现 panic 问题。

NilAway 工具也能捕获这类跨函数的的问题,会报告如下错误:

go 复制代码
➜  ~ nilaway demo.go 
/Users/eddycjy/demo.go:7:9: error: Potential nil panic detected. Observed nil flow from source to dereference point: 
	-> eddycjy/demo.go:4:9: literal `nil` returned from `foo()` in position 0
	-> eddycjy/demo.go:7:9: result 0 of `foo()` dereferenced

上面的例子虽然是同 package 内跨函数的问题识别,但实际上该工具也嫩能够分析跨 package 的调用。

总结

今天针对 Go 里最常见的 nil 指针问题进行了静态分析工具 NilAway 的分享。虽然目前该工具还没有正式的生产可用。

可以明确的是这是大家在 Go 应用上常碰到的场景,可以多加关注后续的更新。另外 NilAway 是基于 go/analysis 标准开发的,后续可以接入 golangci-lint 等相关工具。大家可以继续保持关注!

文章持续更新,可以微信搜【脑子进煎鱼了】阅读,本文 GitHub github.com/eddycjy/blo... 已收录,学习 Go 语言可以看 Go 学习地图和路线,欢迎 Star 催更。

推荐阅读

相关推荐
唐青枫7 小时前
别再把 struct 只当字段集合:Go 结构体从语法到项目实战
go
踏着七彩祥云的小丑18 小时前
Go学习第4天:条件、循环语句+函数
学习·golang·go
tyung2 天前
Go 手写 Wait-Free SPSC 无界队列:无 CAS、无锁、泛型节点池
数据结构·后端·go
踏着七彩祥云的小丑2 天前
Go学习第3天:变量+常量+运算符
开发语言·学习·golang·go
踏着七彩祥云的小丑3 天前
Go学习第2天:程序结构+基础语法+数据类型
开发语言·学习·golang·go
吴佳浩3 天前
AI Infra 的真相:Go 没输,rust也不是取代
后端·rust·go
2601_959644893 天前
2026年权威AI引擎优化服务咨询,专业之选
go
逐光老顽童4 天前
用 Go 实现一个 LLM 路由网关:Thompson Sampling 与自适应故障转移实践
vue.js·go
蓝宝石的傻话4 天前
MiBeeNvr v0.6.0: 延时摄影 + 转码界面 + ONVIF 增强 + 文档重构
go·github
先跑起来再说4 天前
Go 排行榜系统的工程化实现:分布式锁、快照表与定时刷新
分布式·go·gin