专栏首页码农桃花源Go Modules 的智障版本选择

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/dubbo-go@v1.3.0 -> github.com/hashicorp/consul@v1.5.3 -> github.com/envoyproxy/go-control-plane@v0.8.0 cch.com/c -> mosn.io/mosn@v0.11.0 -> github.com/envoyproxy/go-control-plane@v0.6.9

参考资料

[1]

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

[2]

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

本文分享自微信公众号 - 码农桃花源(CoderPark),作者:曹春晖

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-04-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 忠于职守 —— sysmon 线程到底做了什么?(九)

    在 runtime.main() 函数中,执行 runtime_init() 前,会启动一个 sysmon 的监控线程,执行后台监控任务:

    梦醒人间
  • Go 程序是怎样跑起来的

    刚开始写这篇文章的时候,目标非常大,想要探索 Go 程序的一生:编码、编译、汇编、链接、运行、退出。它的每一步具体如何进行,力图弄清 Go 程序的这一生。

    梦醒人间
  • 喜提 redir contributor

    看多了 Go 源代码,看一看应用,尤其是比较短小且有趣的应用代码,感觉很有意思,而且举重若轻。

    梦醒人间
  • go 命令

    建议使用 -gcflags "-N -l" 参数关闭编译器代码优化和函数 内联,避免断点和单步执行无法准确对应源码行,避免小函数和局部变量被优化掉。-o 指定存...

    solate
  • Go语言实战笔记(二)| Go开发工具

    在Go语言中,我们很多操作都是通过go命令进行的,比如我们要执行go文件的编译,就需要使用go build命令,除了build命令之外,还有很多常用的命令,这一...

    飞雪无情
  • Go 1.16 中关于 go get 和 go install 你必须注意的地方

    Go (golang) 已于 18 日发布了 1.16 beta1 版本,至此其主体功能已经基本确定。我看大多数人都在关注 Go 在苹果(Apple) M1 上...

    郭旭东
  • Go命令官方指南【原译】

    如果构建的参数是.go文件的列表,则build会将它们视为指定单个包的源文件列表。

    sunsky
  • 【从零开始学习Go语言】四.Go常用命令释义

    go run 命令用于编译并运行命令源码文件,如果你用vim编辑go文件并希望他暂时跑起来查看效果,使用此命令:go run file_name

    一只特立独行的兔先生
  • 【从零开始学习Go语言】四.Go常用命令释义

    go run 命令用于编译并运行命令源码文件,如果你用vim编辑go文件并希望他暂时跑起来查看效果,使用此命令:go run file_name

    一只特立独行的兔先生
  • 还在为Go依赖安装不上烦恼?

    打开VSCode后,新建一个xx.go文件,右下角会提示安装模块,选择install all:

    公众号guangcity

扫码关注云+社区

领取腾讯云代金券