前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >搞清楚 Go Mod的版本和伪版本,下次别乱用了

搞清楚 Go Mod的版本和伪版本,下次别乱用了

作者头像
KevinYan
发布2022-10-27 10:46:01
5770
发布2022-10-27 10:46:01
举报
文章被收录于专栏:网管叨bi叨网管叨bi叨

关于 Go 项目的依赖管理的日常使用以及遇到的问题怎么解决,俺已经写过两篇文章了。

今天再跟大家唠一下 Go Module 中软件包的版本和伪版本的内容,因为这是一个理想很丰满、现实很骨感的故事。

Module 的版本

关于 Go Module 依赖包的软件版本,这块知识就很中规中矩啦,大部分资料里也都有提及。

Go Modules模块的版本格式为“主版本号.次版本号.修订号”,版本号的递增规则如下:

代码语言:javascript
复制
v1.26.0
 | |  |_ _  修订号
 | | 
 | |_ _ _ _ 次版本号
 |
 |_ _ _ _ _ 主版本号
  1. 主版本号:当你做了不兼容的更新时变更主版本号。
  2. 次版本号:当你做了向下兼容的功能性更新时更改次版本号。
  3. 修订号:当你做了向下兼容的问题补丁修正时更改修订号。

不过当你在真正在项目里使用 Go Module 管理项目依赖的时候,尤其是你们公司内部的私有依赖模式时,你就会发现事情完全没有这么简单。

多数情况下,go.mod 文件里会有一堆依赖他们的版本会是酱婶儿的:

代码语言:javascript
复制
golang.org/x/lint v0.0.0-20200302205851-738671d3881b 
...
code.xxx.com/libs/xyz v1.0.10-0.20220805095508-6c1f3628ef7a

这个就是我们接下来要说的伪版本了。

Module 的伪版本

为什么mod 文件里有这么多伪版本 (pseudo-version) 呢,这里先跟大家插播一个小知识,大家在看技术文档的时候经常会有伪类,伪代码,伪版本这样的术语,他们基本上都是在原来的词根上加一个Pseudo前缀,代表他们不是正式的类、代码、版本?(伪类好像不是那么回事,前端知识已经忘光了,😭),还有那个单词开头的P不发音… 不过好像咱们平时交流的时候念错了也没事,毕竟不少程序员哥哥,都把 alter 念成了alert,也不影响我们改MySQL的表。

Go Module 生成的伪版本主要有两种,其一是这种v0.0.0开头的:

代码语言:javascript
复制
golang.org/x/lint v0.0.0-20200302205851-738671d3881b

这种是因为依赖模块的代码仓库上不存在任何标签,所以go get 默认拉取的是主干分支最新一次commit对应版本的代码,并且在go.mod文件里为模块分配格式为 v0.0.0-主干分支最新一次commit的时间-commit哈希 这样的一个虚拟版本。

第二种是这种非 v0.0.0 开头的伪版本,比如:

代码语言:javascript
复制
code.xxx.com/libs/xyz v1.0.10-0.20220805095508-6c1f3628ef7a

这种一般是作为依赖包的项目本身代码仓库里有打标签发布版本,可是后续我们需要更新包,在测试阶段的时候在项目使用go get 模块名@CommitHash 获取还未正式发布的内容:

代码语言:javascript
复制
go get code.xxx.com/libs/xyz@6c1f3628ef7a

这个时候 Go Module 就会给我们在依赖已发布的版本上进行累加,然后生成伪版本,比如上面那个例子,模块的伪版本以v1.0.10开头就代表模块上一次发布的版本是v1.0.9,你打开模块所在的代码仓库看一下,一定会有一个v1.0.9的标签在那。

这里再放一个伪版本各部分的说明图给大家,方便理解记忆。

gomod 的伪版本规则

关于模块的伪版本,虽然我们掌握了它的生成规则,但使用的时候一定不要自己在 go.mod 文件里去编辑,而是使用上面举例的go get 命令,让 Go Module 自己生成模块的伪版本。

伪版本的乱象

针对在测试、开发阶段的依赖模块,因为不能在主干分支上打标签,我看到网上不少资料推荐以这种方式设置版本:

代码语言:javascript
复制
// 在测试分支上打标签
v1.2.30-test
// 在仿真分支上打标签
v1.2.30-pre

等模块测试通过,就可以在软件包的master分支打出v1.2.30标签,将引用模块的项目中go.mod文件里的依赖声明,更改成正式版本即可。

不过实际我看下来,更多的是使用伪版本的居多,而且很多线上项目在 go.mod 文件里直接就是引用的这些伪版本的模块。

这些问题咋一看起来没有什么事儿,但是我前段时间改了个被降本提效的团队的项目,里面就很多这种使用依赖的伪版本,更坑的是他们没把这个版本里的代码合并到主干,导致我更新了一个新版本,测试的时候,报了一个类似这样的错。

代码语言:javascript
复制
package provided […] but not at required version

Go Module 告诉我某个包在原来的版本的模块里,不在你声明的版本里… 。后来花了挺长时间对比才发现原来使用的版本并没有合并到主干分支上。

这里再次提醒一下大家,项目使用的内部依赖包,上线前一定要确定使用这些软件包在主干上打的标签版本,为什么再次强调一定要在主干分支上打最终的正式标签呢... 因为如果规范不明确,真有大哥从feature分支上打正式标签...

总结

今天给大家介绍了 Go Module 关于模块版本管理的几个小知识,也说了下在开发模块时的一些乱象,咱们最好还是遵守上面说的,测试阶段在测试分支打标签,发布的时候一定要合并到主干上打正式标签,项目不要还依赖着模块的伪版本呢就上线了,发布前检查一下 go.mod 及时更改过来,就不会像我这大冤种,天天给前人填坑啦。

互联网公司风风火火,人来的快走的也快,这些都是团队没有好的规范造成的,打工人也只能接受,但是我们一定要了解一些东西到底怎么用才是正确,怎么建立起良好的规范,才不会出现这种多人协作时一团乱的问题。

好了说了这么多,积极向上的,其实我解决这个问题时心里一直想的是下一波儿降本提效的时候,能不能N+1把我送走😂

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

本文分享自 网管叨bi叨 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Module 的版本
  • Module 的伪版本
  • 伪版本的乱象
  • 总结
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档