Go deadcode:查找没意义的死代码,对于维护项目挺有用!

简介: Go deadcode:查找没意义的死代码,对于维护项目挺有用!

用 deadcode 检测代码


普遍来讲,作为 Go 项目源代码一部分,但在任何执行过程中都无法触及的函数被称为 "死代码",它们会拖累代码库的维护工作。


也会造成程序员在阅读代码时的认知负担,看了半天发现这代码根本没用。或是莫名其妙就被引入模块依赖里里。尴尬得很。


现在我们可以用 deadcode 工具来识别他。


安装方式如下:


$ go install golang.org/x/tools/cmd/deadcode@latest
$ deadcode -help
The deadcode command reports unreachable functions in Go programs.
Usage: deadcode [flags] package...


以下是一个简单 Demo:


func main() {
 var g Greeter
 g = Helloer{}
 g.Greet()
}
type Greeter interface{ Greet() }
type Helloer struct{}
type Goodbyer struct{}
var _ Greeter = Helloer{}
var _ Greeter = Goodbyer{}
func (Helloer) Greet()  { hello() }
func (Goodbyer) Greet() { goodbye() }
func hello()   { fmt.Println("你好,煎鱼!") }
func goodbye() { fmt.Println("再见,煎鱼!") }


运行结果:


$ go run main.go
你好,煎鱼!


咋一眼一看,可能没法知道是哪块代码没用到。还需要多看两眼。


这时候我们只需要借助 deadcode 工具去扫描,一下子就能得到结果了。


执行如下命令并查看输出结果:


$ deadcode .
main.go:20:17: unreachable func: Goodbyer.Greet
main.go:23:6: unreachable func: goodbye


检测结果告诉我们 goodbye 函数和 Goodbyer.Greet 方法都无法访问。也就是这个代码本身的存在是没有运行意义的。


如果你希望清除这些骚扰代码,就可以依据这个结果去做删除代码了。


同时也可以借助命令的子选项 -whylive,让检测工具给我们解释为什么 greet.hello 函数是有效的。

如下解释结果:


$ deadcode -whylive=example.com/greet.hello .
                  example.com/greet.main
dynamic@L0008 --> example.com/greet.Helloer.Greet
 static@L0019 --> example.com/greet.hello
                   example.com/greet.main
  ...


该命令会把 main 开始到函数调用的过程打印出来,作为一种解释。证明这个函数确实是存在使用的。


注意点和发现机制


需要留意的是:deadcode 工具,必须要包含 main 函数。言外之意就是其检测链路是从 main 函数开始的。

否则会产生如下的报错信息:


$ deadcode .
deadcode: no main packages


deadcode 工具本身会加载、解析和类型检查指定的包,然后将其转换为类似编译器的中间表示形式。


然后会使用 Rapid Type Analysis(RTA)的算法来建立可达函数集,最初只包括每个主要包的入口点:main 函数和包初始化函数(分配全局变量并调用名为 init 的函数)。


RTA 会分析每个可达函数的语句体,以此来收集三种所需的类型信息:直接调用的函数集合、通过接口方法进行的动态调用集合以及转换为接口的类型集合。


因此他必须依赖 main 函数作为主入口来做调用链路分析。当然了,这也是相对正常的。总得有个 “客户端” 来做开始逻辑。


我们可以定期在 Go 项目上运行 deadcode 命令(特别是在重构工作之后),以帮助识别程序中不再需要的部分。

但需要留意的是,deadcode 工具还是在发展阶段。复杂场景下,可能无法保证 100% 的准确率,我们最好还是要自己做一遍 double check 和灰度上线。


总结


今天基于官方的《Finding unreachable functions with deadcode》给大家分享了 deadcode 工具的使用和机制。

整体上来讲,还是非常乐见这个工具的诞生和发展的。历史项目维护旧了,很多地方删删改改,堆积久了后,确实会给大家开发造成不少的认知负担和维护成本。


有机会可以体验和实际使用该工具,有一定的价值!

相关文章
|
3月前
|
JSON 运维 Go
Go 项目配置文件的定义和读取
Go 项目配置文件的定义和读取
|
1月前
|
Go
使用go语言将A助手加入项目中
使用go语言将A助手加入项目中
24 2
|
1月前
|
SQL 关系型数据库 MySQL
Go语言项目高效对接SQL数据库:实践技巧与方法
在Go语言项目中,与SQL数据库进行对接是一项基础且重要的任务
57 11
|
1月前
|
存储 Kubernetes Go
Go语言项目组织架构
Go语言项目组织架构
|
3月前
|
JSON 中间件 Go
go语言后端开发学习(四) —— 在go项目中使用Zap日志库
本文详细介绍了如何在Go项目中集成并配置Zap日志库。首先通过`go get -u go.uber.org/zap`命令安装Zap,接着展示了`Logger`与`Sugared Logger`两种日志记录器的基本用法。随后深入探讨了Zap的高级配置,包括如何将日志输出至文件、调整时间格式、记录调用者信息以及日志分割等。最后,文章演示了如何在gin框架中集成Zap,通过自定义中间件实现了日志记录和异常恢复功能。通过这些步骤,读者可以掌握Zap在实际项目中的应用与定制方法
135 1
go语言后端开发学习(四) —— 在go项目中使用Zap日志库
|
3月前
|
API
企业项目迁移go-zero实战(二)
企业项目迁移go-zero实战(二)
|
3月前
|
JSON 缓存 监控
go语言后端开发学习(五)——如何在项目中使用Viper来配置环境
Viper 是一个强大的 Go 语言配置管理库,适用于各类应用,包括 Twelve-Factor Apps。相比仅支持 `.ini` 格式的 `go-ini`,Viper 支持更多配置格式如 JSON、TOML、YAML
go语言后端开发学习(五)——如何在项目中使用Viper来配置环境
|
3月前
|
缓存 JavaScript 前端开发
为开源项目 go-gin-api 增加 WebSocket 模块
为开源项目 go-gin-api 增加 WebSocket 模块
46 2
|
3月前
|
Prometheus Cloud Native NoSQL
Go - 一个对新手很友好的项目(带界面)
Go - 一个对新手很友好的项目(带界面)
39 1
|
3月前
|
SQL NoSQL Go
Go - 实现项目内链路追踪(二)
Go - 实现项目内链路追踪(二)
38 1