10分钟将你的Go工程转换为Go Module模式

引言
自从在Go 1.11和更高版本中引入了Go的新的依赖管理系统以来,GoLang开发人员已经接受了包版本控制解决方案。这样作的用户可使用GoCenter存储库中的不可变公共Go 模块,并经过更健壮、更可靠的Go Pipeline得到更快的构建速度。git

可是,将现有的项目转换为使用Go Module并不老是很容易,尤为是若是该项目已经尝试过GoLang的其余包管理解决方案时。缓存

为了帮助GoLang社区正确地使用Go Module,咱们将使用开源的etcd项目(Kubernetes使用的键值数据存储)做为示例。这是一个最佳实践的实际示例,由于它足够复杂,能够展现一些常见的实践网络

PS:
在上一篇关于Go语言开发的的文章中(传送门:Go 语言依赖管理的优点),咱们介绍了Go 依赖管理的发展历史以及Go Module如何更有效的帮助咱们管理Go语言项目的依赖。今天咱们重点分享如何将你的Go 项目转换为Go Module 项目。ide

Go 项目依赖管理痛点分析
传统GO项目进行第三方模块依赖时,每每是去下载第三方源码,这种方式将存在如下常见问题:
1.性能及稳定性:每次下载从各大VCS系统下载源码性能低,依赖网络环境,稳定性差
2.一致性&可重复性:容易收到依赖源的影响,咱们每每在感知不到模块提供方的改动时,就下载了新版的代码,两次依赖某模块获得的依赖不一致,每每形成前一秒还行,下一秒构建失败的情形,尤为在持续集成系统中
3.协做:源码方式模块基本无版本概念,或不是语义类型,多团队协做困难工具

基于以上问题及痛点,建议转换为Go Module 模式管理Go 项目依赖。附Go Module 基于Go Proxy进行依赖下载的原理图:
10分钟将你的Go工程转换为Go Module模式性能

应用Go Module方式后能够得到如下收益:
1.可用性(标签tag能够从VCS中删除)
2.不变性(能够在VCS中进行更改)
3.快速:(没有git克隆,没有计算元数据,调用更少,性能好)
4.本地统一存储缓存($GOPATH/pkg /mod/cache)测试

Go模块转换最佳实践
咱们以ETCD项目为例进行转换,这个转换过程已经过测试用例的验证,能够到该项目中的Pull Request中查看ui

步骤一:准备go.mod文件
对于之前从未使用过模块的项目(没有go.mod 文件),或者任何如今不推荐的依赖项管理解决方案,这个过程都很是简单。您只须要在项目的根目录中运行go mod tidy。这将生成一个新的、已填充好该项目依赖描述的go.mod文件。版本控制

可是,若是项目使用了那些较老的解决方案之一,好比dep、glide、govendor或godep,那么您将须要运行go mod init来生成填充的go.mod文件。该命令支持旧格式中依赖项描述。blog

etcd项目确实有一个go.mod文件,尽管它从未在项目的构建系统中启用。问题是模块名称没有正确的版本标识符,由于当前版本标记是v2+。因为语义化导入版本控制的影响,须要更改成v3。

其包括执行如下过程:
1.更新etcd的go.mod文件以修正模块名称,使其包含v3后缀。
10分钟将你的Go工程转换为Go Module模式
2.更新全部代码中的Import以包含版本号。咱们编写了一个脚本,以便更容易地修改全部引用。完成后,此更改以下:
10分钟将你的Go工程转换为Go Module模式

步骤二 : 启用Go模块
要使go客户端可以使用go module,须要设置GO111MODULE=on

正如咱们所指出的,etcd项目已经设置了go.mod文件,有人可能认为这已经完成了。但它没有,而该环境变量这种缺失证明了该项目尚未使用go module。

注意:从Go 1.13开始,这一步将再也不须要,由于Go Module将在默认状况下启用

步骤三 : 更新测试中的导入

在上面的过程当中,咱们对组成etcd主模块的go.mod文件进行了更新,以使用v3版本标记。如今主模块被标记为v3,咱们还须要更新etcd项目的测试用例中的Import引用v3,以确保它们导入了主模块的正确版本。

步骤四 : 其余更新

在这些更改以后,您可能但愿保持良好的状态—毕竟,应用程序模块如今已经所有转换为使用go module,并使用正确的版本标记。

不过没那么快。一旦你开始运行测试,你会发现两个额外的场景须要处理:

1.etcd使用了诸如golint、gosimple、staticcheck、ineffassign等静态分析工具,但其中一些工具没有模块意识,没法识别模块路径,而没法经过必要的检查。在etcd的这种场景下,etcd-io/etcd下并无v3文件夹,可是Import导入(或模块路径)包含v3,如etcd-io/etcd/v3。其余工具是模块感知的,但必须在新版本的Go 1.12中可用。若是构建系统在1.11之上,那么它们也须要迁移到1.12。

2.若是使用了protobuf之类的代码生成器。更新.proto文件,以便使用正确版本的导入生成代码。

步骤五 : 加入GoCenter

在构建过程当中,您可能会注意到许多go get命令在etcd的不一样阶段执行。

为了加快GoLang应用程序的构建时间,并确保etcd ppipeline中使用的Go Module版本的不可变性和可用性,使用GoCenter来构建etcd
只需设置GOPROXY=https://gocenter.io。(详细原理可看上文的Go Proxy 原理图)
总结

正如您所看到的,将Go项目转换为使用Go Module方式很是简单,可是有一些细节可能会减慢您的速度。经过选择这个具备丰富场景的项目来演示这个过程,咱们相信咱们达到了大多数须要处理的场景,为您提供了一个很好的示例,覆盖了您可能面临的状况。

最后你们感兴趣能够测试一下旧的依赖管理方式和Go Module方式的性能对比,请参考:
https://jfrog.com/blog/build-times-matter-speed-is-everything/

相关文章
相关标签/搜索