Go Module和Go Vendor | 青训营笔记

707 阅读2分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第2篇笔记

1. 通常目录结构:

$GOPATH/src
  |----appmodule1
        |----*.go
  |----appmodule2
        |----*.go
  |----<main>
       |----main.go
       |----vendor
             |----github.com

注意

  1. 模块指得是你的app的main模块名字,当然也可以使用appname作为目录名,但是这里面的文件例如main.go必须用main作用package name,因为这个模块是应该main模块的;(相比较其他的appmodule1,appmodule2,他们的模块名也应该是路径名)
  2. vender必须在模块目录下面,例如main/vendor,而不能在GOPATH/src目录下面。

2. go编译办法

这和当前工作路径相关:

  1. 如果当前路径在$GOPATH/src,或者其子目录下面,那么vendor有效。

    • PWD=$GOPATH/src/main: go build
    • PWD=$GOPATH/src: go build -o main/main.go
  2. 如果当前路径不在$GOPATH/src,或者其子目录下面,那么vendor无效,因为使用的是module依赖,而不是vendor依赖包管理了。

3.GOPATH的历史

  1. go最早的时候只支持GOPATH
  2. go1.5引入通知设置GO15VENDOREXPERIMENT=1开始支持vendor,注意还是需要GOPATH
  3. go1.11引入module概念,同时引入GO111MODULE=auto|on|off,至此可以不需要GOPATH
  • GO111MODULE=on,使用go module,不使用GOPATH

  • GO111MODULE=off,使用GOPATH,不使用go module

  • GO111MODULE=auto,取决于当前工作路径

    • 如果在GOPATH/src内,等同于GO111MODULE=off,即使用GOPATH
    • 如果在GOPATH/src外,等同于GO111MODULE=on,即不是GOPATH

4.为什么弃用 GOPATH 模式

在 GOPATH 的 $GOPATH/src 下进行 .go 文件或源代码的存储,我们可以称其为 GOPATH 的模式,这个模式,看起来好像没有什么问题,那么为什么我们要弃用呢,参见如下原因:

  • GOPATH 模式下没有版本控制的概念,具有致命的缺陷,至少会造成以下问题:

    • 在执行go get的时候,你无法传达任何的版本信息的期望,也就是说你也无法知道自己当前更新的是哪一个版本,也无法通过指定来拉取自己所期望的具体版本。
    • 在运行 Go 应用程序的时候,你无法保证其它人与你所期望依赖的第三方库是相同的版本,也就是说在项目依赖库的管理上,你无法保证所有人的依赖版本都一致。
    • 你没办法处理 v1、v2、v3 等等不同版本的引用问题,因为 GOPATH 模式下的导入路径都是一样的,都是github.com/foo/bar
  • Go 语言官方从 Go1.11 起开始推进 Go modules(前身vgo),Go1.13 起不再推荐使用 GOPATH 的使用模式,Go modules 也渐趋稳定,因此新项目也没有必要继续使用GOPATH模式。

5.关于go module和vendor的小结

go module和vendor是两个冲突的设计,二者只能选一,不可混用。

  1. vendor依赖的是GOPATH,那么必须设置GOPATH
  2. module不使用GOPATH,那么不能设置GOPATH

从vendor到module迁移: -mod=vendor

6.Go Modules基本使用

创建一个 Go modules 的项目(原则上所创建的目录应该不要放在 GOPATH 之中)。

所提供的命令

在 Go modules 中,我们能够使用如下命令进行操作:

命令作用
go mod init生成 go.mod 文件
go mod download下载 go.mod 文件中指明的所有依赖
go mod tidy整理现有的依赖
go mod graph查看现有的依赖结构
go mod edit编辑 go.mod 文件
go mod vendor导出项目所有的依赖到vendor目录
go mod verify校验一个模块是否被篡改过
go mod why查看为什么需要依赖某模块
go env查看Go modules 下常用的环境变量
查看Go modules 下常用的环境变量:

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