Golang,基于Module和基于GOPATH

本文译自: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)

后面详细介绍了这些命令的运作方式,感兴趣自己去看看吧

Leave a Comment