在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语言软件我版本号的组成。
GO111MODULE
对于模块https://github.com/kataras/iris
引用,不应该直接引用master主库,如果主库变化了,源码可能无法与新版本兼容,导致源码编译不过。这是go modules解决的问题。
go modules
是 golang 1.11 新加的特性。
GO111MODULE 有三个值:off, on和auto(默认值)。
查看所有依赖包
go list -m all
查看包有哪些版本
go list -m -versions github.com/gin-gonic/gin
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
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下面的包,要么完整使用$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并不是一回事。
这个工具包的主要作用有两点:
在项目的这个地方:
github.com/marwan-at-work/example
是一个举子。在example目录下执行mod upgrade或mod downgrade,可以将引用的example模块升级或降低版本号。执行指令后,查看subpkg/subpkg.go文件,可以看到import语句的变化。
这个工具不能代替go mod管理项目依赖,它仅能在特定场景下帮助开发者做一些事情。管理go语言的依赖包,还是推荐使用官方原生的go mod。