深入理解GoModule
1.语义版本机制
1.1 什么是语义版本规范
按照Go Module构建模式,一个符合Go Module要求的版本号,需要按照语义版本规范组成
语义版本规范:语义化版本 2.0.0 | Semantic Versioning
主版本号:主版本号不同的两个版本是互不兼容的
次版本号:主版本号相同的情况下,次版本号的大的,兼容次版本号小的
补丁版本号:主版本号和次版本号相同,补丁版本号大的兼容补丁版本号小的
1.2 Go Module如何使用语义版本规范
1.当新旧两个包是相互兼容的,那包的导入路径应该是相同的
eg:如果项目依赖 github.com/sirupsen/logrus 这个包,不管依赖的是这个包的v1.7.1版本还是 v1.8.1版本,包的导入路径都是
1 | import github.com/sirupsen/logrus |
2.如果新旧两个包不兼容,则包的导入路径不同,导入路径通过在包后面加主版本号的方式区分
eg:如果项目之前依赖github.com/sirupsen/logrus 这个包的v1.7.1,后面需要依赖 v2.7.1版本,那包的导入路径就要变为
1 | import github.com/sirupsen/logrus/v2 |
3.如果主版本号是v0或者v1,则包的导入路径后不用跟主版本号
eg:不管项目依赖github.com/sirupsen/logrus 这个包的v0.7.1还是v1.7.1版本,包的导入路径都是
1 | import github.com/sirupsen/logrus |
2.Go Module的最小版本选择原则
eg:
上图的这种情况,根据Go Module的最小版本选择原则,最终会使用C v1.3.0版本,而不会使用v 1.7.0版本
原因是:对于这个项目来说C v1.3.0版本就够用了,引入更高级别的版本,虽然也可以兼容,但是增加了不稳定性
3.Go Module的6类常规操作
3.1 为当前module添加一个依赖
1.手动在源码中通过import语句导入依赖包
1 | import github.com/google/uuid |
2.下载依赖包并更新go.mod文件
- 方式一:使用go get命令,下载依赖包到本地module缓存里,并更新go.mod文件
1 | $go get github.com/google/uuid |
- 方式二(推荐):使用go mod tidy命令,自动检测,自动下载依赖包并更新go.mod文件
3.2 升级/降级当前依赖的版本(主版本号相同)
1.首先如果升级/降级后的依赖版本和当前版本的版本号相同,就不用修改源代码中的import导入语句
2.修改go.mod文件
- 方式一:使用go get命令,下载升级/降级后的依赖包到本地module缓存里,并更新go.mod文件中依赖包的版本号到升级/降级后的版本
1 | $go get github.com/sirupsen/logrus@v1.7.0 |
- 方式二:先使用go mod edit命令,告知我们需要的升级/降级后的版本,然后再使用go mod tidy命令下载依赖包并更新go.mod文件
1 | $go mod edit -require=github.com/sirupsen/logrus@v1.7.0 |
3.3 升级当前依赖版本到一个不兼容的版本
1.先修改源代码中import导入的依赖包
2.使用go get命令,下载升级后的依赖包并更新go.mod文件
3.4 添加一个主版本号大于1的依赖
1.先修改源代码中import导入的依赖包
2.使用go get命令,下载升级后的依赖包并更新go.mod文件
3.5 移除一个依赖
1.先删除源代码中import导入的依赖包
2.使用go mod tidy命令,自动分析,自动移除依赖包,自动更新go.mod文件
3.6 使用vendor机制
如果使用vendor机制,进行构建时,就会从vendor目录下拉取依赖包,而不是从GoModule的本地缓存中拉取依赖包
如果有特殊情况要使用vendor机制
1.使用go build命令构建时,需要加参数
1 | $go build -mod=vendor |
2.Go v1.14版本后,如果根目录下有vendor目录,则默认使用vendor机制,如果还是想使用Go Module,需要的命令如下
1 | $go build -mod=mod |