前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >go modules:使用 mod 管理项目依赖包,通过vendor实现一键分发编译包

go modules:使用 mod 管理项目依赖包,通过vendor实现一键分发编译包

作者头像
LIYI
发布2020-03-25 18:41:28
5.8K0
发布2020-03-25 18:41:28
举报
文章被收录于专栏:艺述论专栏艺述论专栏

在go语言1.11版本之前,没有modules机制,所有软件包都在安装在$GOPATH/src目录下。不同项目如果引用了同一个软件包的不同版本,就会造成编译麻烦。修改$GOPATH变量是当时一种比较简单的解决方案。

从1.11版本开始,开始有了GO111MODULE变量。因为是自1.11版本支持的,所以名字中有“111”。依靠go语言最新的mod模块,可以将依赖包的不同版本都缓存至$GOPATH/pkg/mod目录下,各个项目通过go.mod文件各取合适的依赖包版本使用。

如果想实现一键分发编译包,通过go mod vendor指令,将依赖包从$GOPATH/pkg/mod目录拷贝至当前项目目录下的vendor目录中。将目录打包,直接分发即可,当然这限同类平台。

如果是不同平台,通过go.mod文件重新下载依赖即可。如果网络不稳定,还可以通过export GOPROXY=https://goproxy.io设置网络代理。

依赖包版本号格式

在理解mod的工作方式之前,需要先了解一下go语言软件我版本号的组成。

  • MAJOR 主版本号,如果有大的版本更新,这种更新往往导致 API 和之前版本不兼容,此时数字加1。
  • MINOR 次版本号,当你做了向下兼容的新 feature,将此版本号升1。
  • PATCH 修订版本号,当你做了向下兼容的修复 bug fix,将此数字加1。

GO111MODULE

对于模块https://github.com/kataras/iris引用,不应该直接引用master主库,如果主库变化了,源码可能无法与新版本兼容,导致源码编译不过。这是go modules解决的问题。

go modules 是 golang 1.11 新加的特性。

GO111MODULE 有三个值:off, on和auto(默认值)。

  • GO111MODULE=off,go命令行将不会支持module功能,寻找依赖包的方式将会沿用旧版本那种通过vendor目录或者GOPATH模式来查找。
  • GO111MODULE=on,go命令行会使用modules,而一点也不会去GOPATH目录下查
  • GO111MODULE=auto,默认值,自动性取决于上下文目录。go命令行将会根据当前目录来决定是否启用module功能。这种情况下可以分为两种情形:
    • 当前目录在GOPATH/src之外且该目录包含go.mod文件
    • 当前文件在包含go.mod文件的目录下面。

查看所有依赖包

go list -m all

查看包有哪些版本

go list -m -versions github.com/gin-gonic/gin

代码语言:javascript
复制
v1.1.1 v1.1.2 v1.1.3 v1.1.4 v1.3.0 v1.4.0 v1.5.0 v1.6.0 v1.6.1

版本可升可降,直接指定版本。

go get github.com/gin-gonic/gin@v1.3.0

go get github.com/gin-gonic/gin@v1.1.4

只需要在依赖包后面加上 @version 就可以了

如何更换版本?

只需要在依赖包后面加上 @version 就可以了

go get github.com/gin-gonic/gin@v1.1.4

go get github.com/gin-gonic/gin@v1.3.0

版本可升可降,直接指定版本。

使用go mod edit直接修改

使用 go mod 来进行版本的切换,这样就需要两个步骤了

go mod edit -require="github.com/gin-gonic/gin@v1.1.4"

go mod tidy:删除未使用的依赖项

go mod tidy

tidy 会自动清理掉不需要的依赖项,同时可以将依赖项更新到当前版本

go mod:查看所有指令

go mod

代码语言:javascript
复制
The commands are:
download    download modules to local cache
edit        edit go.mod from tools or scripts
graph       print module requirement graph
init        initialize new module in current directory
tidy        add missing and remove unused modules
vendor      make vendored copy of dependencies
verify      verify dependencies have expected content
why         explain why packages or modules are needed

只有当使用go mod vendor指令后,才会将当前所有依赖包拷贝至当前项目目录下。

有人说,mod虽好,但是费开发者的电脑磁盘,go mod拉取的软件包都会放在当前目录的pkg/mod目录下面,不像java的maven本地一个集中的目录。其实在go 1.13版本中,go mod下载依赖包目前是放在$GOPATH/pkg/mod目录下,所有项目是共享的。

只有当使用go mod vendor指令后,才会将当前所有依赖包拷贝至当前项目目录下。

项目依赖包的加载顺序

Go 1.11版本支持临时环境变量GO111MODULE,通过该环境变量来控制依赖包的管理方式。当GO111MODULE的值为on时,那么就会使用modules功能,这种模式下,$GOPATH不再作为build时导入的角色,依赖包会存放在$GOPATH/pkg/mod目录下。工程中的依赖包也会从此目录下查找。

当GO111MODULE的值为off时,不再使用modules功能。此时软件包的使用顺序为:

  • 优先使用vendor目录下面的包,
  • 如果vendor下面没有搜索到,再搜索$GOPATH/src下面的包,
  • 如果$GOPATH下面没有搜索到,那么搜索$GOROOT/src下面的包,

要么完整使用vendor下面的包,要么完整使用$GOPATH下面的包,不会混合使用。

当使用go mod vendor指令,将依赖包全部拷贝至当前项目下后,当前项目就可以随意拷贝分发,避免因网络问题造成接收者安装依赖包的麻烦。

关于marwan-at-work/mod

有一个相关的工具包在这个地方:

github.com/marwan-at-work

有教程介绍它可以帮助我们管理依赖包,结束go.mod文件提供自动升级、降低版本的功能。

不要用它代替go mod,管理依赖直接使用go mod指令即可。这个依赖包安装后,在$GOPATH/bin目录下会有一mod二进制文件。执行mod与官方指令go mod并不是一回事。

这个工具包的主要作用有两点:

  • 可以快速在v1、v2或更高版本之间实现依赖的切换,用于快速演示,这确实比较酷
  • 如果代码老旧了,引用的是旧版本,与新版本不兼容导致无法编译,这时候可以通过长高或降纸版本号,让项目成功运行。

在项目的这个地方:

github.com/marwan-at-work/example

是一个举子。在example目录下执行mod upgrade或mod downgrade,可以将引用的example模块升级或降低版本号。执行指令后,查看subpkg/subpkg.go文件,可以看到import语句的变化。

这个工具不能代替go mod管理项目依赖,它仅能在特定场景下帮助开发者做一些事情。管理go语言的依赖包,还是推荐使用官方原生的go mod。

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

本文分享自 艺述论 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档