如何獲取 Go 服務依賴包

在服務治理中,我們有時需要統計業務方服務的依賴包版本號使用情況,以便進行升級和版本兼容,通過 Go 官方提供的 debug.ReadBuildInfo 可以很方便的實現。

debug.ReadBuildInfo

ReadBuildInfo 是 Go 標準庫提供的方法,通過該方法可以讀取打包程序的構建信息,裏面就包括我們想要的依賴包和版本號信息。

// 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)

可以看到該方法返回了兩個返回值:

需要注意的是,只有在啓動 go module 時才能正常獲取到 BuildInfo

下面我們看下 debug.BuildInfo 結構體。

debug.BuildInfo

根據 Go 官方文檔 說明,BuildInfo 表示從運行的二進制文件讀取的構建信息。

type BuildInfo struct {
	Path string    // main 包路徑,比如:command-line-arguments
	Main Module    // main 包信息
	Deps []*Module // 依賴包列表信息
}

繼續看下 Module 結構體:

type Module struct {
	Path    string  // 包路徑
	Version string  // 包版本號
	Sum     string  // 包校驗值
	Replace *Module // 表示是否進行了 replace 替換
}

Module 表示一個模塊信息,main 包也是個 Module。

下面我們寫個代碼示例看下 BuildInfo 具體長什麼樣。

首先,寫一個 go.mod:

module gomod01

go 1.16

require (
	github.com/davecgh/go-spew v1.1.1
)

然後,編寫 main.go

package main

import (
	"runtime/debug"

	"github.com/davecgh/go-spew/spew"
)

func main() {
	res, ok := debug.ReadBuildInfo()
	if ok {
		spew.Dump(res)
	}
}

運行:

(*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,以及依賴的第三方包和版本號都能拿到。

小結

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://maratrix.cn/post/2021/04/28/go-deps/