最开始的GOPATH
GOPATH可以理解为工作目录,一般这个目录下有如下的三个文件夹
bin
存放编译后生成的二进制可执行文件pkg
存放编译后生成的.a
文件src
存放项目的源代码:自己写的代码和go get
下载的包这种将自己的包和下载的包全部放在
$FOPATH/src
下进行管理的方式称为GOPATH模式,至此可能不会觉得这种方案有什么问题,但是当真正开始使用GOPATH去开发的适合,就会遇到各种问题,其中最严重的就是版本管理问题- 你无法在你的项目中,使用指定版本的包,因为不同版本的包的导入方法也都一样
- 其他人运行你的开发的程序时,无法保证他下载的包版本是你所期望的版本,当对方使用了其他版本,有可能导致程序无法正常运行
- 在本地,一个包只能保留一个版本,意味着你在本地开发的所有项目,都得用同一个版本的包,这几乎是不可能的。
go vendor模式的过度
为了解决GOPATH模式下不同项目无法使用多个版本的问题,Go v1.5 开始支持 vendor。
思路是在每个项目根目录下新建一个vendor
目录和和verdor.json
文件,每个项目所需的依赖都只会下载到自己vendor目录下,项目之间的依赖包互不影响。在编译时,v1.5 的 Go 在你设置了开启 GO15VENDOREXPERIMENT=1
(注:这个变量在 v1.6 版本默认为1,但是在 v1.7 后,已去掉该环境变量,默认开启 vendor 特性,无需你手动设置)后,会提升 vendor 目录的依赖包搜索路径的优先级(相较于 GOPATH)。
这种方式虽然解决了一些问题,但是解决的并不完美
- 如果多个项目用到了同一个包的同一个版本,这个包会存在于该机器上的不同目录下,不仅对磁盘空间是一种浪费,而且没法对第三方包进行集中式的管理(分散在各个角落)。
- 并且如果要分享开源你的项目,你需要将你的所有的依赖包悉数上传,别人使用的时候,除了你的项目源码外,还有所有的依赖包全部下载下来,才能保证别人使用的时候,不会因为版本问题导致项目不能如你预期那样正常运行。
算得上好用的go mod
go modules
出现于v1.11,成长于v1.12,丰富于v1.13,成熟于v1.14。从v1.11开始,go env
就多了个GO111MODULE
环境变量,有三个值可选。
GO111MODULE=off
,禁用模块支持,编译时会从GOPATH和vendor文件夹中查找包。GO111MODULE=on
,启用模块支持,编译时会忽略GOPATH和vendor文件夹,只根据 go.mod下载依赖。GO111MODULE=auto
,当项目在$GOPATH/src外且项目根目录有go.mod文件时,自动开启模块支持。
可以在环境变量上进行设置
也可以使用
go env
命令
$ go env -w GO111MODULE="on"
那么go modules
是如何管理依赖的呢
go mod 不再依靠 $GOPATH
,使得它可以脱离 GOPATH
来创建项目,使用go modules
之后,项目的目录下会多出go.mod
和go.sum
两个文件,这两个文件正是go modules
的核心所在。
go.mod
的内容比较容易理解
-
第一行:模块的引用路径
-
第二行:项目使用的 go 版本
-
第三行:项目所需的直接依赖包及其版本
module github.com/BingmingWong/module-test
go 1.14
require (
example.com/apple v0.1.2
example.com/banana v1.2.3
example.com/banana/v2 v2.3.4
example.com/pear // indirect
example.com/strawberry // incompatible
)
exclude example.com/banana v1.2.4
replace(
golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac => github.com/golang/crypto v0.0.0-20180820150726-614d502a4dac
golang.org/x/net v0.0.0-20180821023952-922f4815f713 => github.com/golang/net v0.0.0-20180826012351-8a410e7b638d
golang.org/x/text v0.3.0 => github.com/golang/text v0.3.0
)
反观 go.sum
文件,就比较复杂了,密密麻麻的。
每一行都是由 模块路径
,模块版本
,哈希检验值
组成,其中哈希检验值是用来保证当前缓存的模块不会被篡改。hash 是以h1:开头的字符串,表示生成checksum的算法是第一版的hash算法(sha256)。
想了解如何使用go mod可以点击链接。
总结
GOPATH 做为 Golang 的第一个包管理模式,只能保证你能用,但不保证好用,而 go vendor 解决了 GOPATH 忽视包版的本管理,保证好用,但是还不够好用,直到 go mod 的推出后,才使 Golang 包的依赖管理有了一个能让 Gopher 都统一比较满意的方案,达到了能用且好用的标准。