这是我参与「第三届青训营 -后端场」笔记创作活动的第2篇笔记
1. 通常目录结构:
$GOPATH/src
|----appmodule1
|----*.go
|----appmodule2
|----*.go
|----<main>
|----main.go
|----vendor
|----github.com
注意
- 模块指得是你的app的main模块名字,当然也可以使用appname作为目录名,但是这里面的文件例如main.go必须用main作用package name,因为这个模块是应该main模块的;(相比较其他的appmodule1,appmodule2,他们的模块名也应该是路径名)
- vender必须在模块目录下面,例如main/vendor,而不能在GOPATH/src目录下面。
2. go编译办法
这和当前工作路径相关:
-
如果当前路径在$GOPATH/src,或者其子目录下面,那么vendor有效。
- PWD=$GOPATH/src/main: go build
- PWD=$GOPATH/src: go build -o main/main.go
-
如果当前路径不在$GOPATH/src,或者其子目录下面,那么vendor无效,因为使用的是module依赖,而不是vendor依赖包管理了。
3.GOPATH的历史
- go最早的时候只支持GOPATH
- go1.5引入通知设置GO15VENDOREXPERIMENT=1开始支持vendor,注意还是需要GOPATH
- 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是两个冲突的设计,二者只能选一,不可混用。
- vendor依赖的是GOPATH,那么必须设置GOPATH
- 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=""
...等