本文译自:https://go.dev/ref/mod#non-module-compat
Golang的导包有两种模式,一种是基于GOPATH的(老),一种是基于Module的(新),自1.16版本后,默认开启基于Module的方式,不管 go.mod
文件存不存在
对非Module模式项目的兼容方式
对即使没有go.mod
的项目(非module项目),go也能使用module模式处理package
当你需要导入的模块和其仓库根目录相同时,若在其仓库根目录没有 go.mod
文件,go就会在module cache(module下载下来后保存在本地的路径)中自动生成一个 go.mod
,但其中只包含了module path(例:module golang.org/x/net),并没有包含该module依赖的其他module(即 go.mod 中的require语句),所以,当其他module需要依赖该module时就需要一些额外的require语句来获取这些依赖(即在require后面跟着 // indirect 的那些个依赖)
版本号兼容
对于版本号大于1的module,需在其module path上加上版本号后缀,例如 /golang.org/x/v2/net 表示x这个module的第2个版本(这里的v2不会被当作是目录名)
但对于一些较老的module,它已经迭代了很多版本了,但当时还没有这个规定。可以使用 +incompatible
来兼容它们。例如 require example.com/m v4.1.2+incompatible
。
基于module的命令
绝大多数命令都可以运行在这两个模式下,在module模式下,go命令使用 go.mod 文件去寻找依赖,一般情况下都是在 GOPATH/pkg/mod
目录下寻找,如果找不到也会下载到该目录下。在GOPATH模式下,go命令会在 vendor 目录和 GOPATH 目录下寻找依赖
在go 1.16 版本后,不管是否存在go.mod文件都会使用module模式(早期会根据是否存在该文件而做判断)
- 当
GO111MODULE=off
,go命令会忽视 go.mod 文件直接使用GOPATH模式 - 当
GO111MODULE=on
或者为空时,则会使用module模式,即使 go.mod 文件不存在 - 当
GO111MODULE=auto
,若当前文件夹或任何父文件夹存在 go.mod 文件,则使用module模式
在module模式下,GOPATH不再作为编译时导包方式了,但它仍然用作存储下载下来的依赖目录(GOPATH/pkg/mod 目录)和install之后的文件保存目录(GOPATH/bin)
编译命令
一些加载包信息的命令都可以使用module模式,其中包括
- go build
- go fix
- go generate
- go get
- go install
- go list
- go run
- go test
- go vet
在module模式下运行时,这些命令会使用 go.mod 文件去解析packages,它们可以使用以下参数
-mod
参数 go.mod 是否自动更新和是否使用vendor
目录-mod=mod
忽略 vendor 目录,自动更新 go.mod,例如当import的module还没有被声明依赖时,就会自动在go.mod文件中添加该依赖-mod=readonly
忽略 vendor 目录,需手动更新 go.mod,否则报错mod=vendor
使用vendor下的包,但不会下载网络上的包,也不会使用module cache中的包(GOPATH/pkg/mod)- 如果go版本大于等于1.14,并且存在vendor目录,则会自动使用
mod=vendor
方式,否则使用 readonly 模式
-modcacherw
在module cache创建的目录将具有读写权限(否则就只读)-modfile=file.mod
指定 .mod 文件(默认 go.mod)
后面详细介绍了这些命令的运作方式,感兴趣自己去看看吧