TOC

GO111MODULE 是什么?

每一个 Golang 初学者都会遇到 GOPATH 和 Go Module 的问题,至少在最近的一两年是这样的。

简单的说,就是由于 Golang 诞生于谷歌,所以早期的项目工程化受谷歌内部开发流程影响很大。谷歌内部不同项目的代码放在一起,方便相互引用。GOPATH 就是这种代码管理方式的体现,所有的包都放在一个固定的开发目录下。

但是外面的世界,可能是受开源生态的影响,我们习惯将代码拆分成不同的包,分散在不通的仓库,需要什么包就导入什么包。所以虽然有一些人一直在吹捧 GOPATH 模式,但是大多数人还是喜欢传统的包模式。

所以在 Go Module 之前,官方或者社区也都有出一些解决方案,其中最有名的是 depvender。但随着最终方案 Go Module 的确定,他们已经完成了历史使命,而我最近两个月才开始学 Go,当然就跳过他们了。

GOPATH 和 Go Module 的核心问题就是定义我们代码中导入的包在哪里。

我们的包来自什么地方?

  1. 本地代码目录
  2. GOPATH 目录: ~/go
  3. GOROOT 目录: /usr/lib/go -> /usr/lib/go-1.15, 子目录又都链接到 /usr/share/go-1.15/

go get2 安装包在 GOPATH/src 目录,包导入的查询也是在 GOPATH/srcGOROOT/src 下进行。

需要记住的两个点:

  1. Go 是需要编译的,最后以二进制文件作为输出(我总是会忘记这一点);
  2. Go 依赖管理的一个重要理念:去中心化。

需要编译,就需要找依赖库
去中心化,就不能是 PyPI,CPAN,Maven 这种,Go 给出的方案是走代码托管平台。

两种模式

  • GOPATH 模式
    1. 早期版本中(1.11 以前1)是 GOPATH 模式,当时只有一个 go get 用于从远程拉代码。
      1. 1.8 之前必须设置 GOPATH 环境变量,1.8 开始可以不设置,默认是 ~/go
    2. GOPATH 目录相当于就是用户的工作目录,所有的外部包都必须放在这个目录下。
  • Module 模式
    1. Go 1.11 (2018-08) 开始引入 Module 模式,每个包使用一个 go.mod 文件。
      同时加入了 GO111MODULE 环境变量,表示是否开启 Module 模式,选项有 on, off, auto,默认值是 auto
      auto 的行为:如果不在 GOPATH/src 中,并且找到 go.mod 文件则使用 Module 模式,否则就是 GOPATH 模式。
      比如有个包叫做 golang.org/x/toolsgo get 会从 golang.org 下载代码到本地的 GOPATH/src/golang.org/x/tools
    2. Go 1.13 (2019/09) 开始,auto 的行为改为:只要找到 go.mod,就使用 Module 模式。
    3. Go 1.16 (2021/02) 开始 GO111MODULE 默认值为 on
    4. 在可预见的将来,GOPATH 模式会被彻底移除,GO111MODULE 环境变量也将成为历史。

在官方的依赖管理工具 go mod 出现之前,还有过 等方案。

参考资料与拓展阅读


  1. 版本历史

    version date
    go1.17 2021-08-16
    go1.16 2021-02-16
    go1.15 2020-08-11
    go1.14 2020-02-25
    go1.13 2019-09-03
    go1.12 2019-02-25
    go1.11 2018-08-24
    go1.10 2018-02-16
    go1.9 2017-08-24
    go1.8 2017-02-16
    go1.7 2016-08-15
    go1.6 2016-02-17
    go1.5 2015-08-19
    go1.4 2014-12-10
    go1.3 2014-06-18
    go1.2 2013-12-01
    go1.1 2013-05-13
    go1 2012-03-28

  2. go get 的作用是拉取或更新依赖包,支持从 GitHub, BitBucket, Google Code Project Hosting, Launchpad 上下载。
    如果本地代码托管服务需要支持 go get 的话,好像是需要对服务进行一些调整或者拓展。GitLab 支持。