![image.png](https://static.golangjob.cn/221008/1bdcc22199604fbeca3f4f5b46e28984.png)
Golang 开发的模式演进;
下栽地止:https://www.ubkz.com/t-3325.html
从 Go 出生开始,用户就一直在使用 GOPATH 这个环境变量,随着 Go 语言的快速发展和不断壮大,由 GOPATH 引起的编译依赖问题也开始逐渐出现。终于在2019 年, Golang 迎来 10 周年之际,Google Go 团队终于开始把目光投向了这一伴随了 Golang 十年的环境变量。
GOPATH的使用
目前在 Go 中存在两种开发模式,GOPATH mode 和 Go modules mode。
在 Go modules 之前,Go 开发中的依赖管理使用 GOPATH 开发模式。在 GOPATH 开发模式中,Go 命令使用 GOPATH 环境变量来实现以下几个功能:
go install 命令安装二进制库到 $GOBIN, 其默认路径为 $GOPATH/bin。
go install 命令安装编译好的包到 $GOPATH/pkg/ 中,例如将 example.com/y/z 安装到 $GOPATH/pkg/example.com/y/z.a。
go get 命令下载源码包到 $GOPATH/src/ 中,例如将 example.com/y/z 下载到 $GOPATH/src/example。
Go modules的发展历程
GOPATH mode 开发模式是终将要被淘汰的,Go 官方在整个 Go 开发生态系统中添加 package version 这一概念,进而引入 Go modules 开发模式。从 GOPATH mode 开发模式变换到 Go modules 是一个漫长的过程,它已经经历了数个 Go 的发行版本:
Go 1.11 (2018 年 8 月) 引入了 GO111MODULE 环境变量,其默认值为 auto。如果设置该变量 GO111MODULE=off, 那么 go 命令将始终使用 GOPATH mode 开发模式。如果设置该变量 GO111MODULE=on,go 命令将始终使用 Go modules 开发模式。如果设置该变量 GO111MODULE=auto (或者不设置),go 命令行会根据当前工作目录来决定使用哪种模式,如果当前目录在 $GOPATH/src 以外,并且在根目录下存在 go.mod 文件,那么 go 命令会启用 Go module 模式,否则使用 GOPATH 开发模式。这个规则保证了所有在 $GOPATH/src 中使用 auto 值时原有编译不受影响,并且还可以在其他目录中来体验最新的 Go module 开发模式。
Go 1.13 (2019 年 8 月) 调整了 GO111MODULE=auto 模式中对 $GOPATH/src 的限制,如果一个代码库在 $GOPATH/src 中,并且有 go.mod 文件的存在, go 命令会启用 module 开发模式。这允许用户继续在基于导入的层次结构中组织他们的检出代码,但使用模块进行个别仓库的导入。
Go 1.16 (2021 年 2 月) 会将 GO111MODULE=on 做为默认值,默认启用 go module 开发模式,也就是说,默认情况下 GOPATH 开发模式将被彻底关闭。如果用户需要使用 GOPATH 开发模式可以指定环境变量 GO111MODULE=auto 或者 GO111MODULE=off。
Go 1.NN (???) 将会废弃 GO111MODULE 环境变量和 GOPATH 开发模式,默认完全使用 module 开发模式。
GOPATH 与Go modules的相爱想杀
针对大家关心的几个问题,笔者对此作出如下回答:
Q1:GOPATH 变量会被移除吗?
A:不会,GOPATH 变量不会被移除。未来废弃 GOPATH 开发模式并不是指删除 GOPATH 环境变量,它会继续保留,主要作用如下:
go install 命令安装二进制到 $GOBIN 目录,其默认位置为 $GOPATH/bin。
go get 命令缓存下载的 modules 到 $GOMODCACHE 目录,默认位置为 $GOPATH/pkg/mod。
go get 命令缓存下载的 checksum 数据到 $GOPATH/pkg/sumdb 目录。
Q2:我还可以继续在 `GOPATH/src/import/path` 中创建代码库吗?
A:可以,很多开发者以这样的文件结构来组织自己的仓库,你只需要在自己创建的仓库中添加 go.mod 文件。
Q3: 如果我想测试修改一个我需要的依赖库,我改怎么做?
A:如果你编译自己的项目时依赖了一些未发布的变更,你可以使用 go.mod 的 replace来实现你的需求。
举个例子,如果你已经将 golang.org/x/website 和 golang.org/x/tools 下载到 $GOPATH/src/ 目录下,那么你可以在 $GOPATH/src/golang.org/x/website/go.mod 中添加下面的指令来完成替换:
replace golang.org/x/tools => $GOPATH/src/golang.org/x/tools
当然,replace 指令是不感知 GOPATH 的,将代码下载到其他目录也一样可以。
有疑问加站长微信联系(非本文作者)