go项目管理的前世今生

792 阅读1分钟

最开始的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)。

这种方式虽然解决了一些问题,但是解决的并不完美

  • 如果多个项目用到了同一个包的同一个版本,这个包会存在于该机器上的不同目录下,不仅对磁盘空间是一种浪费,而且没法对第三方包进行集中式的管理(分散在各个角落)。
  • 并且如果要分享开源你的项目,你需要将你的所有的依赖包悉数上传,别人使用的时候,除了你的项目源码外,还有所有的依赖包全部下载下来,才能保证别人使用的时候,不会因为版本问题导致项目不能如你预期那样正常运行。

详细的使用方法可以看链接1链接2

算得上好用的go mod

go modules出现于v1.11,成长于v1.12,丰富于v1.13,成熟于v1.14。从v1.11开始,go env就多了个GO111MODULE环境变量,有三个值可选。

  1. GO111MODULE=off,禁用模块支持,编译时会从GOPATH和vendor文件夹中查找包。
  2. GO111MODULE=on,启用模块支持,编译时会忽略GOPATH和vendor文件夹,只根据 go.mod下载依赖。
  3. GO111MODULE=auto,当项目在$GOPATH/src外且项目根目录有go.mod文件时,自动开启模块支持。

可以在环境变量上进行设置 也可以使用go env命令

$ go env -w GO111MODULE="on"

那么go modules是如何管理依赖的呢

go mod 不再依靠 $GOPATH,使得它可以脱离 GOPATH 来创建项目,使用go modules之后,项目的目录下会多出go.modgo.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 都统一比较满意的方案,达到了能用且好用的标准。