Modules简介

奇技指南

最近项目需要开始正式的接触golang的项目,开源项目中使用了最新的以来管理go mod,就跟进了解了相关的一些内容,经过几年的尝试和改进, 现在的版本也是作者希望能够持续十年的设计,也期望能够学习到作者们的思想,提升自己对版本依赖的认识。

本文转载自360云计算

背景介绍

历史介绍

1.Makefile, goinstall和go get

最早是通过Makefile的形式进行编译,连接程序。后来的goinstall能够在无额外配置的情况拉取到相应的代码,此时只能使用在标准库中。go get解决了开发者之间的代码共享问题,能够通过git等进行代码共享。

2.Versioning和API Stability

通过import的路经中添加相应的版本信息达到了引用不同版的效果。

3.Vendoring和Reproducible Builds

由于go get没有版本相关的信息,所以不能提供一个可以可稳定重复的编译过程。vendor通过拷贝相应的代码到vendor目录下,依赖项不会变更除非手动修改其中的依赖项。

4.An Official Package Management Experiment

dep是官方的依赖管理实验项目,主要是用来探索最佳的实践,是找到最终的解决的重要的一步。

解决的问题

  1. 官方的定义

module是一组相关的package的集合,作为一个整体进行版本控制。module记录精确的依赖需求并创建可重复的构建。

一个repo可以包含一个或者多个module,一个module可以包含一个或者多个package,一个package是一个路经下包含一个或者多个文件。

module必须是经过语义版本semver的。

1. 版本控制

如何引入一个向下不兼容的版本?

import的兼容规则如下

If an old package and a new package have the same import path,

the new package must be backwards compatible with the old package.

如果使用相同的import路经,则新版本必须是兼容就版本的。go是通过不兼容的版本使用不同的import路经来区分的,

例如 import path和import path/v2的方式

2.同一个主版本采用最低版本选择策略进行版本选择?

最小版本选择,即为选择所有的版本中(不同的主版本是不同的package)选择版本最大的一个版本,也是可用的最小版本。

设计目标

鼓励用户打标签,使得更加的可读,并且能够帮助使用者明确哪些是已经发布的,哪些是正在开发中的不依赖具体的版本控制既可以在一个repo中使用一个module,也可以一个repo下使用多个module,并且各自进行版本控制

能够添加自己的代理

删除之前的vendor目录

基本操作

创建Module

  1. 创建一个目录,新建hello.go文档

2.添加相应的测试文档

3.执行测试,确认程序正常运行

注意需要关闭掉相应的module强制设置,确保GO111MODULE不为on,否则会得到 go: cannot find main module; see ‘go help modules’

初始化为module

查看相应的go.mod

执行测试

说明: go命令能够自动从go.mod中导入指定的依赖项。如果在go.mod中没有找到特定的依赖项的情况

则会从对应的package中自动的查找相应的module,并且把结果写入到go.mod中。导入的module的版本默认选择最新的版本(latest),go.mod中默认自动添加的只有直接依赖的module,并不包含间接依赖的module。

查看新的go.mod

执行test

通过上述结果可以看出,第二次执行go test的时候,由于go.mod已经是最新状态,并且需要的module已经缓存在本地了,就不再执行上述的获取,展开的过程了。

查看module的所有依赖

列出了module的所以依赖项,第一行列出的是当前module(也称为主module),依赖的module则按照module的路径进行排序列在下面的内容.

查看生成的go.sum

go.sum中保存的是模块对应的哈希值,该值可以保证后续下载的版本和第一次下载的版本没有被非预期的修改。

升级依赖

升级golang.org/x/text

重新检查依赖列表

从上面的结果中可以看出,golang.org/x/text从之前的版本已经升级到了v0.3.2的版本,更新之后的版本信息已经添加到了go.mod,后面添加了indirect表明该依赖项不是主module直接依赖的。

查询可用的所有依赖

更新到指定版本

添加一个新的主版本

添加quoteV3版本

添加对应的测试代码

执行测试

获取最新的依赖关系

不同的主版本采用不同的导入路径,通过这种方式来提供不兼容的版本升级。v0,v1是直接使用module的路径就可以了,v2及以上的版本必须要添加相应的版本信息path/v2等方式。同一个主版本的不同子版本必须要保证向下的兼容性,也就是同一个主版本只会选择一个版本。这种方式保证了我们在使用新版本的特性的时候,又可以暂时不迁移依赖旧版本的代码。

删除不再使用的依赖

查看现有的依赖关系

从上面的依赖列表中还是依然又v1.5.2,go build或者go test这样的命令,能够添加没有的以来项目但是不能够安全的删除掉相应的依赖。安全的删除一个依赖需要检查module里面的所有package是否依赖该module,而build,test命令都没有加载相应的信息,所以不能够安全的删除相应的module。

go mod tidy

通过这个命令能够删除掉不再需要的依赖module

问题

1.go list -m all?

按照什么排序策略进行排序

2.提交代码的时候一定要提交go.mod和go.sum不然会出现checksum的时候出错的情况

使用中遇到的问题

如何进行依赖库的代码开发?

可以用replace的方式,replace可以替换成本地的路经,来达到使用本地代码的作用。

如何使用自由仓库进行依赖库的开发?

设置git的地址转化就可以达到预期的目的,是否可以通过proxy的形式来做到类似的效果,还没有具体研究,后面会去研究以下proxy相关的内容。

go.mod和go.sum的提交?

提交相应的变更的时候,务必记得提交相应的go.sum,不然会出现后续的sum检查不通过。

关注我们

界世的你当不

只做你的肩膀

360官方技术公众号 

技术干货|一手资讯|精彩活动

空·