前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何调试 Go mod 的各种异常

如何调试 Go mod 的各种异常

作者头像
poslua
发布2020-11-05 18:41:24
1.8K0
发布2020-11-05 18:41:24
举报
文章被收录于专栏:posluaposlua

Go mod 自从诞生之日就带来了太多太多的争议,当然不能否认它的设计初衷是好的。然而在调试其各种异常时,却浪费了太多开发者的时间。可以毫不客气的说,从来没有一种语言的版本管理,能让人如此崩溃

本文记录了一些我的踩坑经验,希望能给还在挣扎中的 Gopher 一些帮助。

go get

先来看看最近我遇到的一个问题:

代码语言:javascript
复制
$ go mod tidygo: foo.bar.com/foo/bar@v0.1.0: git remote add origin -- https://foo.bar.com/foo/bar.git in /root/goforge/pkg/mod/cache/vcs/e8ae9003fdd7f44246f94c535282e58436b3568a39734a76af8fac7b716a59b2: exit status 128:        fatal: remote origin already exists.

光从字面上来看,像是一个 git 的问题。一顿 go mod whygo mod graph 操作后,也没有得到什么有价值的信息。

以我的个人摸索经验来看,whygraph 的输出就是一坨垃圾,只会给开发者带来更多的心智负担。

实际上,调试 go mod 问题最好的工具是 go get ,这样可以只会输出异常模块的依赖树,去掉那些烦人的干扰信息。如果再加上 -x 选项后,更是屡试不爽。继续拿我遇到的这个问题开刀:

代码语言:javascript
复制
$ go get -x foo.bar.com/foo/bar# get https://foo.bar.com/foo/bar?go-get=1# get https://foo.bar.com/foo/bar?go-get=1: 200 OK (0.508s)mkdir -p /root/goforge/pkg/mod/cache/vcs # git3 https://foo.bar.com/foo/bar.git# lock /root/goforge/pkg/mod/cache/vcs/e8ae9003fdd7f44246f94c535282e58436b3568a39734a76af8fac7b716a59b2.lockmkdir -p /root/goforge/pkg/mod/cache/vcs/e8ae9003fdd7f44246f94c535282e58436b3568a39734a76af8fac7b716a59b2 # git3 https://foo.bar.com/foo/bar.gitcd /root/goforge/pkg/mod/cache/vcs/e8ae9003fdd7f44246f94c535282e58436b3568a39734a76af8fac7b716a59b2; git init --bare0.011s # cd /root/goforge/pkg/mod/cache/vcs/e8ae9003fdd7f44246f94c535282e58436b3568a39734a76af8fac7b716a59b2; git init --barecd /root/goforge/pkg/mod/cache/vcs/e8ae9003fdd7f44246f94c535282e58436b3568a39734a76af8fac7b716a59b2; git remote add origin -- https://foo.bar.com/foo/bar.git0.006s # cd /root/goforge/pkg/mod/cache/vcs/e8ae9003fdd7f44246f94c535282e58436b3568a39734a76af8fac7b716a59b2; git remote add origin -- https://foo.bar.com/foo/bar.gitgo: foo.bar.com/foo/bar@v0.1.0: git remote add origin -- https://foo.bar.com/foo/bar.git in /root/goforge/pkg/mod/cache/vcs/e8ae9003fdd7f44246f94c535282e58436b3568a39734a76af8fac7b716a59b2: exit status 128:        fatal: remote origin already exists.

瞧,go get -x 会帮你把每个步骤的操作都打出来。显然这个问题确实由 git 引起。大概是 go get 拉取模块时,会先创建一个裸仓库,然后 add origin 。问题就发生在 add origin 这步,git 认为已经有一个 origin 存在了。这是为啥呢?不妨去手动复现下:

代码语言:javascript
复制
$ mkdir git_test$ cd git_test$ git init$ git remote add origin -- https://foo.bar.com/foo/bar.gitfatal: remote origin already exists.

继续看看,现在这个仓库的 origin 是啥:

代码语言:javascript
复制
$ git remote -vorigin

看到这里,突然想起我的 git 配置了 origin 默认指向 HEAD

代码语言:javascript
复制
$ git config -l | grep originbranch.master.remote=originremote.origin.push=HEAD

git 2.20 以上已经在一个空的 origin 上继续 add 了

删除了这个选项后:git config --global --unset remote.origin.push, 终于可以拉取成功了。

replace

试想这么一种场景,假设有个项目 foo 依赖 a 的 v1.0.0 版本,而 foo 依赖的 b 依赖了 a 的 v2.0.0 版本。那么这个时候 foo 的 mod 其实最终会依赖 a 的 v2.0.0 版本。如果你需要 foo 强行依赖 v1.0.0 版本,这个时候就派上了 replace 的上场。直接修改 go.mod 文件,添加:replace a => a v1.0.0 即可。

但是实际情况,往往会更复杂。比如 b 需要 a v2.0.0 的一些新特性的话,简单的 replace 往往不能解决这个问题。如何解决呢?自己去处理。比如,Kuma[1] 自己维护了一个 vendored 文件夹 replace 到本地来处理这种问题;Kubernetes[2] 也有个自己的 staging

mod cache

需要注意的是 go 1.12 版本之前,mod cache 并不是并发安全的,同一个环境并发构建可能会产生竞态。而最新的 go 1.15 还提供了环境变量 GOMODCACHE 来指定 mod cache 的位置,CI 工具可以利用这项加快构建速度。

引用链接

[1] Kuma: https://github.com/kumahq/kuma/blob/master/vendored/README.md [2] Kubernetes: https://github.com/kubernetes/kubernetes/blob/master/staging/README.md

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-11-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 poslua 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • go get
  • replace
  • mod cache
    • 引用链接
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档