本文翻译自《go.mod file reference》。
目录
每个Go模块都由一个go.mod文件定义,该文件描述模块的属性,包括它对其他模块和Go版本的依赖关系。
这些属性包括:
- 当前模块的模块路径。这应该是Go工具可以从中下载模块代码的位置,例如模块代码的存储库的位置。当与模块的版本号结合使用时,它用作唯一标识符。它也是模块中所有包的包路径的前缀。有关Go如何定位模块的更多信息,请参阅Go模块参考手册。
- 当前模块所需的最低Go版本。
- 当前模块所需的其他模块的最低版本的一个列表。
- 可选地,用另一个模块版本或本地目录替换所需模块,或排除所需模块的特定版本。
当你运行go mod init
命令时,Go会生成一个go.mod文件。以下示例创建一个go.mod文件,将模块的模块路径设置为example/mymodule
:
$ go mod init example/mymodule
使用go
命令来管理依赖项。这些命令确保go.mod文件中描述的需求保持一致,并且go.mod文件的内容有效。这些命令包括go get
和go mod tidy
以及go mod edit
命令。
有关go
命令的参考,请参阅Command go。你可以通过键入go help command-name
从命令行获得帮助,就像go help mod tidy
一样。
另请参阅
例子
go.mod文件包含指令,如下所示。这些将在本主题的其他地方进行描述。
module example.com/mymodule
go 1.14
require (
example.com/othermodule v1.2.3
example.com/thismodule v1.2.3
example.com/thatmodule v1.2.3
)
replace example.com/thatmodule => ../thatmodule
exclude example.com/thismodule v1.3.0
模块
声明模块的模块路径,这是模块的唯一标识符(与模块版本号组合使用时)。模块路径成为模块包含的所有包的导入前缀。
有关更多信息,请参阅Go模块参考手册中的module
指令。
语法
module module-path
其中module-path
代表模块的模块路径,通常是Go工具可以从中下载模块代码的存储库的位置。对于模块v2及更高版本,模块路径必须以主版本号结尾,例如/v2
。
例子
以下示例中的example.com
代表可以从中下载模块代码的存储库的域名。
v0或v1模块的模块声明:
module example.com/mymodule
v2模块的模块路径:
module example.com/mymodule/v2
笔记
模块路径必须能唯一标识你的模块。对于大多数模块,其路径是一个URL,go
命令可以在其中找到模块的代码(或重定向到模块的代码)。对于永远不会直接被下载的模块,模块路径可以是由你决定的某个名称,确保唯一性即可。前缀example/
保留用于示例。
有关详细信息,请参阅管理依赖项。
实际上,模块路径通常是模块源代码的存储库的域名和模块代码在存储库中的路径。go
命令在下载模块版本或解决依赖关系时,就依赖于此形式。
即使你一开始并不打算让你的模块可供其他人使用,按照此形式确定其存储库路径也是一种最佳实践,这将帮助你在以后发布模块时避免重命名该模块。
如果一开始你不知道模块的最终存储库位置,请暂时使用安全的替代品,例如你拥有的域名或你能控制的名称(例如你的公司名称),然后紧跟着模块的名称或源代码的目录名。有关更多信息,请参阅管理依赖项。
例如,如果你在stringtools
目录中进行开发,你的临时模块路径可以是<company-name>/stringtools
,如下例所示,其中company-name
是你公司的名称:
go mod init <company-name>/stringtools
go
表示模块是在go
指令指定的Go版本下编写的。
有关更多信息,请参阅Go模块参考手册中的go
指令。
语法
go minimum-go-version
其中minimum-go-version
代表编译此模块中的包所需的最低的Go版本。
例子
模块必须在Go 1.14或更高版本上运行:
go 1.14
笔记
go
指令最初旨在支持对 Go 语言的向后不兼容更改(请参阅Go 2转换)。自从引入模块以来没有不兼容的语言更改,但go
指令仍然影响新语言功能的使用:
- 对于模块中的包,编译器拒绝使用在
go
指令指定的版本之后引入的语言功能。例如,如果一个模块有指令go 1.12
,它的包可能不会使用像1_000_000
这样的数值字面量,因为这是在Go 1.13中引入的语言新特性。 - 如果用较旧的Go版本构建模块的其中一个包,并遇到编译错误,则该错误会指出该模块是为较新的Go版本编写的。例如,假设一个模块有
go 1.13
指令,并且一个包使用了数值字面量1_000_000
。如果该包使用Go 1.12来构建,编译器会注意到代码是为Go 1.13编写的。
此外,go
命令根据go
指令指定的版本号更改其行为。这具有以下效果:
- 在
go 1.14
或更高版本中,可以启用自动vendor(译者注:vendor模式的模块管理属于Go语言在1.11版本之前的其中一种模块管理方式,Go 1.11引入的基于go.mod文件的模块管理方式才是最先进的模块管理方式)。如果文件vendor/modules.txt存在并且与go.mod一致,则无需显式使用-mod=vendor
标志。 - 在
go 1.16
或更高版本中,all
包模式仅匹配主模块(main模块)中的包和测试导入的包。这是自引入模块以来由go mod vendor
保留的同一组包。在较低Go版本中,all
还包括主模块中导入的包及其测试文件等等。 - 在
go 1.17
或更高版本中:- go.mod文件为每个模块包含一个明确的
require
指令,该指令提供由主模块中的包或测试文件导入的任何包。(在go 1.16
及更低版本中,仅当最小版本选择会选择不同版本时才会包含间接依赖。)此额外信息支持模块图化简和模块懒加载。 - 因为可能比以前的
go
版本有更多// indirect
,间接依赖被记录在go.mod文件中的一个单独的块中。 go mod vendor
会忽略vendor目录中依赖项的go.mod和go.sum文件。(这允许在vendor的子目录中调用go
命令以识别正确的主模块。)go mod vendor
将每个依赖项的go.mod文件中的Go版本记录在vendor/modules.txt文件中。
- go.mod文件为每个模块包含一个明确的
go.mod文件最多可以包含一个go
指令。大多数命令都会在当前Go版本中添加一个go
指令(如果还不存在的话)。
需求(require)
将模块声明为当前模块的依赖项,指定所需模块的最低版本。
有关更多信息,请参阅Go模块参考手册中的require
指令。
语法
require module-path module-version
module-path
代表模块的模块路径,通常是模块源代码的存储库的域名再加上模块名称。对于模块版本v2及更高版本,此值必须以主版本号结尾,例如/v2
。
module-version
代表模块的版本号。这可以是发行版的版本号,例如v1.23,也可以是Go生成的伪版本号,例如v0.0.0-20200921210052-fa0125251cc4。
例子
需求已发布的版本v1.2.3:
require example.com/othermodule v1.2.3
需求在其存储库中尚未加标签的版本,使用Go工具生成伪版本号:
require example.com/othermodule v0.0.0-20200921210052-fa0125251cc4
笔记
当你运行go
命令(例如go get
)时,go
命令会插入包含导入包的每个模块的指令。当模块在其存储库中尚未加标签时,Go会分配一个伪版本号,它会在你运行命令时自动生成。
通过使用replace
指令,你可以让Go从存储库以外的位置需求模块。
有关版本号的更多信息,请参阅模块版本编号。
有关管理依赖关系的详细信息,请参阅以下内容:
替换(replace)
用另一个模块版本或本地目录替换特定模块版本(或所有版本)的内容。Go工具将在解析依赖关系时使用替换路径。
有关更多信息,请参阅Go模块参考手册中的replace
指令。
语法
replace module-path [module-version] => replacement-path [replacement-version]
module-path
代表要替换的模块路径。
module-version
,可选,代表要替换的特定版本号。如果省略此版本号,则模块的所有版本都将被替换为箭头右侧的内容。
replacement-path
代表Go应查找的所需模块的路径。这可以是模块路径,也可以是本地文件系统上的模块源代码所在目录的路径。如果这是模块路径,则必须指定replacement-version
。如果这是本地路径,则不能使用replacement-version
。
replacement-version
,可选,代表用来替换的模块的版本号。只有当replacement-path
是模块路径(而不是本地目录路径)时,才能指定replacement-version
。
例子
- 被替换为模块存储库的分叉(fork)版本
在以下示例中,example.com/othermodule的任何版本都将被替换为其分支版本。
require example.com/othermodule v1.2.3
replace example.com/othermodule => example.com/myfork/othermodule v1.2.3-fixed
用另一个模块路径替换一个模块时,不要更改被替换模块里的包的导入语句。
有关使用模块代码的分叉版本的更多信息,请参阅从自己的存储库分叉版本请求外部模块代码。
- 被替换为模块的其他版本
以下示例指定使用v1.2.3版本,而不是该模块的任何其他版本。
require example.com/othermodule v1.2.2
replace example.com/othermodule => example.com/othermodule v1.2.3
以下示例将模块v1.2.5版本替换为同一模块的v1.2.3版本。
replace example.com/othermodule v1.2.5 => example.com/othermodule v1.2.3
- 被替换为本地代码
以下示例指定使用本地目录里的代码替换模块的所有版本。
require example.com/othermodule v1.2.3
replace example.com/othermodule => ../othermodule
以下示例指定本地目录里的代码仅替换v1.2.5版本。
require example.com/othermodule v1.2.5
replace example.com/othermodule v1.2.5 => ../othermodule
有关使用模块代码的本地副本的更多信息,请参阅需求本地目录中的模块代码。
笔记
如果要使用其他路径来查找模块的源,请使用replace
指令将模块路径值临时替换为其他值。这具有将Go对模块的搜索重定向到替换的位置的效果。不需要更改包导入路径即可使用替换路径。
可以使用exclude
和replace
指令来控制构建时依赖关系的解析。这些指令在依赖当前模块的模块中会被忽略。
replace
指令在以下情况下很有用:
- 你正在开发一个新模块,其代码尚未在存储库中。你希望使用客户端对本地版本进行测试。
- 你发现了某个依赖项的一个问题,你克隆该依赖项的存储库到本地,修复这个问题,并使用该本地存储库测试修复是否成功。
请注意,单独的replace
指令不会将模块添加到模块图中。require
指令还需要引用在主(main)模块的go.mod文件或依赖项的go.mod文件中被替换的模块版本。如果没有要替换的特定版本,可以使用假版本,如下例所示。请注意,这将破坏依赖于该模块的模块,因为replace
指令仅应用于主模块。
require example.com/mod v0.0.0-replace
replace example.com/mod v0.0.0-replace => ./mod
有关替换所需的模块(包括使用Go工具进行更改)的更多信息,请参阅:
有关版本号的更多信息,请参阅模块版本编号。
排除(exclude)
指定要从当前模块的依赖关系图中排除的模块或模块版本。
有关详细信息,请参阅Go模块参考手册中的exclude
指令。
语法
exclude module-path module-version
module-path
代表要排除的模块的模块路径。
module-version
代表特定的版本号。
例子
排除example.com/their模块版本v1.3.0:
exclude example.com/theirmodule v1.3.0
笔记
使用exclude
指令排除间接需求但由于某种原因无法加载的模块的特定版本。例如,你可以使用它排除校验和(checksum)无效的模块版本。
在构建当前模块(主模块)时,使用exclude
和replace
指令来控制对构建时依赖关系的解析。这些指令在依赖于当前模块的模块中被忽略。
你可以使用go mod edit命令
来排除模块,如下例所示。
go mod edit -exclude=example.com/[email protected]
有关版本号的更多信息,请参阅模块版本编号。
撤回(retract)
指示由go.mod定义的模块的版本或某个范围的版本不应该被依赖。当版本未成熟就发布或发布版本后发现严重问题时,retract
指令非常有用。
有关更多信息,请参阅Go模块参考手册中的retract
指令。
retract version // rationale
retract [version-low,version-high] // rationale
version
代表要撤回的单个版本。
version-low
代表要撤回的版本范围的下限。
version-high
代表要撤回的版本范围的上限。version-low
和version-high
都包含在范围内。
rationale
是解释撤回原因的可选注释。可能显示在发给用户的消息中。
例子
撤回单个版本:
retract v1.1.0 // 意外发布。
撤回一个范围的版本:
retract [v1.0.0,v1.0.5] // 在某些平台会破坏构建。
笔记
使用retract
指令指示某个模块的早期版本不应被使用。用户无法使用go get
、go mod tidy
或其他命令自动升级到被撤回的版本。用户使用go list -m -u
命令将在可更新到的版本列表中看不到被撤回的版本。
撤回的版本应该保持可用,以便已经依赖它们的用户能够构建他们的包。即使从源存储库中删除了撤回的版本,它也可能在proxy.golang.org等镜像上仍然可用。依赖撤回的版本的用户在相关模块上运行go get
或go list -m -u
时可能会收到通知。
go
命令通过读取模块最新版本的go.mod文件中的retract指令来发现被撤回的版本。最新版本按优先顺序为:
1 其最高版本号(如果有的话)
2 其最高预发布版本号(如果有的话)
3 存储库默认分支顶端的伪版本号。
新增一个撤回版本时,几乎总是需要加标签一个新的更高的版本,以便go
命令在模块的最新版本中看到retract
指令。
你可以发布一个唯一目的是发出撤回信息的新版本。在这种情况下,该新版本也可以自行撤回。
例如,如果意外加标签v1.0.0,可以使用以下指令加标签v1.0.1:
retract v1.0.0 // 意外发布。
retract v1.0.1 // 只包含撤回指令。
不幸的是,一旦发布了版本,就无法更改。如果稍后为其他commit加标签v1.0.0,go
命令可能会在go.sum或校验和数据库中检测到不匹配的值。
模块的撤回版本通常不会出现在go list -m -versions
的输出中,但你可以使用-reacted
选项来显示它们。有关更多信息,请参阅Go模块参考手册中的go list -m
。