用过Java 的同学都知道,对依赖的管理经历了从原始的手动引入jar包,到使用maven等自动化管理工具去引入第三方依赖的过程,从而可以使用别人已经开发好的优秀工具。如果使用过Python的同学可能会熟练的使用pip install 第三方的工具包。Java 和Python的第三方工具包都是集中式管理的,使用maven 或者是pip 都是从对应的管理中心下载更新依赖。当然还有 npm、yarn、gradle等其他语言的依赖版本工具。

在go语言中,第三方依赖的管理工具经过了一个漫长的发展过程。在GO1.11 发布之前govendor、dep等工具百花齐放。直到go mod 出现,开始一统天下。go 的依赖非常简单粗暴,只要依赖源码就可以了。例如:

import  "github.com/jinzhu/gorm"

github.com/jinzhu/gorm 就是gorm的GitHub项目路径。

GOPATH时期

Go 在1.11 之前使用GOPATH模式进行依赖的管理。安装部署go环境,使用go 进行开发的时候强制被要求要设置GOPATH(当然安装过程中也会默认指定$GOPATH=~/go)。 要在GOPATH路径下新建 src /bin /pkg文件夹。

➜ ~/go
├── bin  # 存储go编译生成的二进制可执行文件,一般会把该路径配置到PATH中,PATH=$PATH:$GOPATH/bin
├── pkg  # 存储预编译的目标文件,以加快后续的编译速度 
└── src  # 存储Go的源代码,一般以$GOPATH/src/github.com/foo/bar的路径存放

➜  go go env |grep GOPATH
GOPATH="/Users/bytedance/go"

在这种模式下,如果使用go get 拉取外部依赖会自动下载并安装到$GOPATH/src 目录下。

这种模式下,go get没有版本管理的概念,无法处理依赖不同版本的问题,因为同一个依赖都存在同一个路径下面。

在Go官方还没有推出Go Modules 的时候,go的依赖管理工具可谓是百花齐放,例如 govendor, dep,但是最终Go Modules发布,平息了诸侯割据的局面。


GO Modules

Go1.11 开始推出Go Modules ,Go1.13开始不再推荐使用GOPATH。意思就是说你可以在任何路径下存放你的Go源码文件, 不用再像以前一样非得放到$GOPATH/src中。 每一个go项目 都是一个 Modules。vgo 是Go Modules的前身。

在Go Modules环境下出现了一个很重要的环境变量GO111MODULE

➜ ~ go env
GO111MODULE="auto"
GOPROXY="https://proxy.golang.org,direct"
GONOPROXY=""
GOSUMDB="sum.golang.org"
GONOSUMDB=""
GOPRIVATE=""

如果要对go 的环境变量进行设置,可以使用

go env -w GO111MODULE=on  # 设置go 环境变量
go env -u # 恢复初始设置

GO111MODULE

GO111MODULE 这个环境变量是用来作为使用Go Modules 的开关。可以说这个变量是历史产物,很有肯能会在将来Go的新版本中去除掉。

GO111MODULE="auto" # 只要项目包含了go.mod 文件的话就启用Go modules, 在Go1.11-1.14 中是默认值
GO111MODULE="on"   # 启用Go Modules
GO111MODULE="off"  # 禁用Go Modules, 对老的项目进行兼容

GOPROXY

GOPROXY 是Go Modules的代理,可以通过镜像站点快速拉取(集中式的概念?),可以设置多个代理。

GOPROXY="https://proxy.golang.org,direct"

direct的意思是如果通过代理获取不到go get 就会通过源地址直接去抓取

go mod

创建Go Modules的基本命令

➜  ~ go mod
Go mod provides access to operations on modules.

Note that support for modules is built into all the go commands,
not just 'go mod'. For example, day-to-day adding, removing, upgrading,
and downgrading of dependencies should be done using 'go get'.
See 'go help modules' for an overview of module functionality.
# 所有的go commands 都支持 modules。
Usage:

        go mod <command> [arguments]

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

Use "go help mod <command>" for more information about a command.