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 催更。

推荐阅读

相关推荐
蒙娜丽宁3 天前
Go语言错误处理详解
ios·golang·go·xcode·go1.19
qq_172805594 天前
GO Govaluate
开发语言·后端·golang·go
littleschemer4 天前
Go缓存系统
缓存·go·cache·bigcache
程序者王大川5 天前
【GO开发】MacOS上搭建GO的基础环境-Hello World
开发语言·后端·macos·golang·go
Grassto5 天前
Gitlab 中几种不同的认证机制(Access Tokens,SSH Keys,Deploy Tokens,Deploy Keys)
go·ssh·gitlab·ci
高兴的才哥6 天前
kubevpn 教程
kubernetes·go·开发工具·telepresence·bridge to k8s
少林码僧7 天前
sqlx1.3.4版本的问题
go
蒙娜丽宁7 天前
Go语言结构体和元组全面解析
开发语言·后端·golang·go
蒙娜丽宁7 天前
深入解析Go语言的类型方法、接口与反射
java·开发语言·golang·go
三里清风_7 天前
Docker概述
运维·docker·容器·go