项目改用GoModules管理依赖的方法和经验总结

贺大伟 · · 660 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Go语言官方提供的依赖包管理工具已经发布很久了,有很多大佬的文章对Go Modules做了非常详尽的介绍,比如煎鱼大佬的: Go Modules终极入门(文章链接:https://juejin.cn/post/6844903433846145038)。

今天的文章我想跟大家聊一下我们项目在从govendor迁移到Go Modules这个过程中总结的几点经验,如果你平时负责的项目早已开始使用Go Modules,这些内容可能对你来说有点小儿科。

环境变量设置

GO111MODULE

这个环境变量是Go Modules功能的开关,目前的默认值是auto,代表只要项目包含了go.mod文件的话就自动开启Go Modules。如果之前没有设置过这个变量,这一步可以直接忽略,从其他包依赖管理工具向Go Modules迁移的时候,我们需要确认一下是不是以前在环境变量中设置过GO111MODULE=off

GOPROXY

Go Modules拉取依赖软件包的默认镜像源站点是https://proxy.golang.org,由于众所周知的问题这个域名在国内访问受限,因此需要使用GOPROXY环境变量设置国内的镜像站点。

GOPROXY=https://goproxy.cn

GOPRIVATE

这个环境变量主要是为项目依赖的一些公司内部的公共软件包准备的,一般是设置成代码仓库站点的域名。假如我公司所有项目都放在用GitLab搭建的内部代码仓库站点,这个站点的域名是code.lazycorp.com,那么我们就把这个环境变量设置成

GOPRIVATE=code.lazycorp.com

这样设置的话,所有路径前缀为code.lazycorp.com的模块都不会再经过GOPROXY指定的镜像站点拉取模块对应的软件包,转而去code.lazycorp.com拉取软件包。

这里提一个小技巧,假如你自己开发的时候不想污染电脑系统里的全局环境变量,可以选择在GoLand里开启Go Modules支持和设置环境变量,这样在GoLand内编译运行程序时也能正常使用Go Modules。

GoLand配置截图

Replace完成版本替换

replace指令的本意是在go.mod文件里完成用一个模块版本替换已经require的模块版本的功能,比如:

module code.lazycorp.com/buzz/practice// 这名是我瞎起的

go1.13

replace(

google.golang.org/grpc v1.33.0=> google.golang.org/grpc v1.26.0

)

require (

google.golang.org/grpc v1.33.0

)

这里的replace指令标识了,使用grpc的v1.26.0版本,替换require里声明的v1.33.0版本。

不过也正好有replace命令,才能解决好几个软件包版本兼容的问题,我遇到的软件包兼容问题主要出在Etcd和gRPC上。

Etcd比较诡异,它里面的bbolt子库的模块名叫go.etcd.io/bbolt但是自己的源码使用这个库时在代码里使用的import路径却是github.com/coreos/bbolt。再加上Etcd提供的软件包与v1.30版本以上的gRPC相互之间不兼容,所以如果gRPC使用了Etcd Naming做服务发现和负载均衡,目前只能通过replace指令对这两个模块进行版本替换。

replace (

github.com/coreos/bbolt =>go.etcd.io/bbolt v1.3.5

google.golang.org/grpc v1.33.0=> google.golang.org/grpc v1.26.0

)

模块的版本控制

模块的版本号会与软件包的tag相对应,比如上面的模块引用google.golang.org/grpc v1.26.0对应于grpc在GitHub上代码仓库的名叫v.1.26.0的标签。

注意标签的名字不能随便命名,比如类似v2020....的标签,Go Modules是没法识别的。

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

v1.26.0

| |  |_ _  修订号

| |

| |_ _ _ _ 次版本号

|

|_ _ _ _ _ 主版本号

主版本号:当你做了不兼容的更新时变更主版本号。

次版本号:当你做了向下兼容的功能性更新时更改次版本号。

修订号:   当你做了向下兼容的问题补丁修正时更改修订号。

测试和生产阶段的模块版本管理

假如我们对公司的公共包做了修改,那么怎么对公共包打标签呢?不能说在测试、仿真和生产阶段给都要给软件包打上不同版本的标签吧,这样代码仓库的标签管理起来容易混乱。

针对这种情况可以将版本信息追加到“主版本号.次版本号.修订号”的后面,作为延伸,比如:

// 在测试分支上打标签

v1.2.30-test

// 在仿真分支上打标签

v1.2.30-pre

这样等测试通过,引用公共软件包的项目需要上线的时候,就可以在公共软件包的master分支打出v1.2.30标签,将待发布项目中go.mod文件里的引用更改成正式版本即可。

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

常用的命令

go mod init 初始化go.mod文件,一般建新项目时才会用这个命令。

go mod tidy 整理现有依赖,修改go.mod文件后执行会更新依赖。

go mod graph 查看现有的依赖结构。

go mod vendor 导出项目所有依赖到vendor目录 (不建议使用)。

这里列出go mod vendor命令是提醒大家,如果使用go mod vendor, 会在项目里生成一个vendor目录把所有依赖导出放到这里面。此后Go Modules在项目里会去vendor里查找引用的依赖包而不是默认的$GOPATH/pkg/mod目录。

假如我们主动更新了依赖包,还需要再次执行go mod vendor把更新导出到vendor目录,项目才能真正引用到更新后的依赖包。

所以既然开始使用Go Modules了,就应该尽量忘记vendor ,另外旧项目从govendor改用Go Modules时的第一步也是先把项目里的vendor目录删掉,再按照文章里的步骤进行操作 。


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:贺大伟

查看原文:项目改用GoModules管理依赖的方法和经验总结

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

660 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传