Go Modules 的智障版本選擇

之前 go mod 用的比較少,而且一直聽社區有各種抱怨,所以也興趣寥寥。新公司的項目直接使用了 go mod,本來覺得無非是個簡單的工具,不需要學習,結果在一個簡單的依賴上卻浪費了很多時間。

先來看看我碰到的例子:

package main


import "fmt"


import registry "github.com/apache/dubbo-go/registry"
import zk "github.com/apache/dubbo-go/registry/zookeeper"
import xds "mosn.io/mosn/pkg/xds"


func main() {
  var r registry.Registry
  fmt.Println(r)
  var z zk.Option
  fmt.Println(z)
  var x xds.Client
  fmt.Println(x)
}


導致衝突的原因,可以隨便找個目錄 go mod init 一下,然後 go build。然而編譯不過去。實際上是因爲 go mod 幫我選擇了 github.com/envoyproxy/go-control-plane 這個庫的錯誤版本,mosn 中直接依賴了這個庫的 0.6.9 版本,但是在 go build 的時候被非常“好心”地升級到了 0.8.0,怎麼回事?

圖比較明顯,go mod why 現在顯然是一坨垃圾。只能通過 go mod graph|grep 來找原因。

這裏有個問題,我的程序其實並沒有依賴 dubbo-go 裏的 consul 這部分代碼,我們用 go mod vendor 把程序的外部依賴保存下來,也可以得到驗證:

/Users/xargin/test/gomod/vendor/github.com/apache/dubbo-go
~/t/g/v/g/a/dubbo-go git:master ❯❯❯ grep -iR consul ./                       
~/t/g/v/g/a/dubbo-go git:master ❯❯❯

所以這裏 go mod 幫我們選擇了一個連間接依賴都算不上的外部庫指定的版本來進行更新。知道原因的話,解決方法也就簡單了,本來對 github.com/envoyproxy/go-control-plane 有依賴的也就只有 mosn,只要 replace 就好:

replace github.com/envoyproxy/go-control-plane => github.com/envoyproxy/go-control-plane v0.6.9

這裏的問題還算簡單,如果碰上大項目,出了 go build 不出來的問題,還得用 go mod graph 一個一個去 grep,心累。

現在 go mod 提供的工具其實也並不方便。看看前幾天的一篇文章:《etcd go module 的災難》[1]

用起來真是不省心。

有一些網友已經做了 go mod graph 的可視化,但是碰上大項目,基本出來的圖不是給人看的:

對於碰到依賴衝突的用戶,其實主要是想看關鍵包的依賴路徑。以及衝突發生的路徑。

簡單寫了一個小工具[2]來支持這個訴求。上面提到的例子會輸出很多可能衝突的 pkg,找一下 go-control-plane

Conflict in pkg github.com/envoyproxy/go-control-plane paths are:
 cch.com/c -> github.com/apache/[email protected] -> github.com/hashicorp/[email protected] -> github.com/envoyproxy/[email protected]
 cch.com/c -> mosn.io/[email protected] -> github.com/envoyproxy/[email protected]

參考資料

[1]

《etcd go module 的災難》: https://colobu.com/2020/04/09/accidents-of-etcd-and-go-module/

[2]

小工具: https://github.com/cch123/gomod-conflict-detect

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章