在服务治理中,我们有时需要统计业务方服务的依赖包版本号使用情况,以便进行升级和版本兼容,通过 Go 官方提供的 debug.ReadBuildInfo
可以很方便的实现。
debug.ReadBuildInfo
ReadBuildInfo 是 Go 标准库提供的方法,通过该方法可以读取打包程序的构建信息,里面就包括我们想要的依赖包和版本号信息。
1
2
3
|
// ReadBuildInfo returns the build information embedded in the running binary.
// The information is available only in binaries built with module support.
func ReadBuildInfo() (info *BuildInfo, ok bool)
|
可以看到该方法返回了两个返回值:
*BuildInfo
表示构建信息
ok
表示是否成功拿到构建信息
需要注意的是,只有在启动 go module
时才能正常获取到 BuildInfo
。
下面我们看下 debug.BuildInfo
结构体。
debug.BuildInfo
根据 Go 官方文档 说明,BuildInfo 表示从运行的二进制文件读取的构建信息。
1
2
3
4
5
|
type BuildInfo struct {
Path string // main 包路径,比如:command-line-arguments
Main Module // main 包信息
Deps []*Module // 依赖包列表信息
}
|
继续看下 Module
结构体:
1
2
3
4
5
6
|
type Module struct {
Path string // 包路径
Version string // 包版本号
Sum string // 包校验值
Replace *Module // 表示是否进行了 replace 替换
}
|
Module 表示一个模块信息,main 包也是个 Module。
下面我们写个代码示例看下 BuildInfo 具体长什么样。
首先,写一个 go.mod:
1
2
3
4
5
6
7
|
module gomod01
go 1.16
require (
github.com/davecgh/go-spew v1.1.1
)
|
然后,编写 main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package main
import (
"runtime/debug"
"github.com/davecgh/go-spew/spew"
)
func main() {
res, ok := debug.ReadBuildInfo()
if ok {
spew.Dump(res)
}
}
|
运行:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
(*debug.BuildInfo)(0xc0000522a0)({
Path: (string) (len=22) "command-line-arguments",
Main: (debug.Module) {
Path: (string) (len=7) "gomod01",
Version: (string) (len=7) "(devel)",
Sum: (string) "",
Replace: (*debug.Module)(<nil>)
},
Deps: ([]*debug.Module) (len=1 cap=1) {
(*debug.Module)(0xc00006a040)({
Path: (string) (len=26) "github.com/davecgh/go-spew",
Version: (string) (len=6) "v1.1.1",
Sum: (string) (len=47) "h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=",
Replace: (*debug.Module)(<nil>)
})
}
})
|
可以看到,当前 Go 程序的模块名是 gomod01,以及依赖的第三方包和版本号都能拿到。
小结
- 官方提供的
debug.ReadBuildInfo
可以很方便的读取依赖包
- Go 服务必须启用 go module(go1.16 默认开启)