前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go mod 七宗罪

Go mod 七宗罪

作者头像
梦醒人间
发布2021-03-17 10:12:29
5730
发布2021-03-17 10:12:29
举报
文章被收录于专栏:码农桃花源码农桃花源

go mod 是 rsc 主导设计的 Go 版本管理工具,借鉴了 Google 内部的高大上版本管理方式,摒弃了开源社区的版本管理成功经验,借助 MVS 算法,希望能够走出一条不一样的路,然而从发布以来给广大 Gopher 带来了各种各样的麻烦。本文简单列举一部分罪状,Google 的并不一定总是世界的。

当然,随着 Go 1.16 的发布,其中有些罪证可能已经不成立了,读者可以自行甄别。

Go 命令的副作用

Go list,Go test,Go build,所有命令都会去拉取依赖,有些库是用被墙的服务做了重定向,只是执行一下 go test,然后就被卡一年是家常便饭。

按照 "By design" 的说法,Google 内部的依赖库版本都会尽量使用能够兼容的最新版本。对于墙内的我们来说,我不管执行什么 Go 命令怎么都卡。逐渐患上 go test PTSD。

解法:配置 GOPROXY 代理,虽然拉取依赖还是慢。

形同虚设的 semver 规范

社区里不遵守 semver 规范的库很多,有的开源库在 1.7.4 ~ 1.7.5 中进行了 breaking change,而按照 semver 的定义,这是不应该发生的。go mod 过度高估了开源社区的节操。

一开始,我们以为这只是社区的节操问题,直到我们碰到了 gRPC。

好样的哦,Google 工程师。

无法应对删库

leftpad 悲剧重演

js 社区使用集中式的 npm 来管理依赖,在几年前发生过一次因为作者删库,导致几乎所有互联网巨头的前端项目全部 build 失败的悲剧。同时 js 社区也进行了一些反思 how one programmer broke the internet[1]have we forgotten how to program[2]

npm 好歹还是集中式的版本管理方式,Go 号称分布式,但大多 Go 的依赖库都是存在 Github 上,如果 Github 上的原作者删除了该库,那么也会导致大多数的依赖用户 build 失败。

即使看起来我们可以靠 go.mod 和 go.sum 来实现 reproducible build,实际的情况是,像 k8s 这样的项目,依然会把庞大的依赖库放在自己 repo 的 vendor 里。

在笔者从 dd 离职时,也曾经不小心删除过一个认为应该没有人再依赖的个人库,当时给前同事们也造成了一些麻烦。

Github release/tag 水土不服

在 Github 上发布 lib 的 release,或者给某个 commit 打 tag 之后,我们依然可以对这些 tag 和 release 进行编辑:

我们经常看到,有些库的作者在发布一个 release 之后,又删除了这个 release,或对这个 release 进行了编辑。对于用户来说,这样就会依赖一个已经“消失”了的版本,在不存储 vendor 的情况下,reproducible build 沦为笑谈。

goproxy 的实现并不统一

不知道是否是因为 goproxy 并无规范,在使用不同的代理帮助我们加速下载依赖时,会出现各种不同的错误。

例如作者 A 开发的 goproxy,在某个库不存在时,会返回 404。而作者 B 开发的 goproxy,在某个库不存在时,会返回 500。着实令人困惑。

而 goproxy 本身的实现基本都是惰性下载,所以新发布的库,我们要走 goproxy 来测试时,就需要手动 go get 触发。而大多 goproxy 的实现并没有查询功能,goproxy 服务内部到底什么时候同步好了,可以 go get 了,还是 go get 的过程中发生失败了。作为用户是不可查的。

go get 到的 lib 版本在 go build 时被修改

在 go get 时,可以 go get lib@ver 来获取指定版本的依赖,但是在 go build 时可能发现又被修改成了别的版本(比如被升级了),非常反直觉。

我们想要锁定具体的版本,只能使用 replace。

版本信息扩散

由于 go mod 的设计,版本信息被包含在了 import 路径中。当依赖库从 v1 升级至 v2 时,几乎一定意味着我们代码中大量的 import 路径需要修改。

修改不兼容的 api 就挺累的了。

go.sum 合并冲突

因为上面讲到的一系列问题,go.sum 在多人维护的大项目上,经常会发生变动,也就经常会有冲突。对于中心化版本管理系统来说,这个问题根本就不存在。对于 go mod 来说,go.sum 合并本来是个纯追加逻辑。

但这些冲突还是会浪费我们的时间。

如果你也曾经被 go mod 烦到骂娘,欢迎在评论区分享你的故事。

同时,也欢迎关注作者的公众号:

欢迎关注 TechPaper 公众号。

TechPaper

[1]

how one programmer broke the internet: https://qz.com/646467/how-one-programmer-broke-the-internet-by-deleting-a-tiny-piece-of-code/

[2]

have we forgotten how to program: https://www.davidhaney.io/npm-left-pad-have-we-forgotten-how-to-program/

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

本文分享自 码农桃花源 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Go 命令的副作用
  • 形同虚设的 semver 规范
  • 无法应对删库
    • leftpad 悲剧重演
      • Github release/tag 水土不服
      • goproxy 的实现并不统一
      • go get 到的 lib 版本在 go build 时被修改
      • 版本信息扩散
      • go.sum 合并冲突
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档