go.mod 文件参考
每个 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
命令的参考,请参阅 命令 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
module
声明模块的模块路径,它是模块的唯一标识符(与模块版本号结合使用)。模块路径成为模块包含的所有包的导入前缀。
有关更多信息,请参阅 Go 模块参考中的 module
指令。
语法
module module-path
- module-path
- 模块的模块路径,通常是 Go 工具可以从中下载模块的存储库位置。对于 v2 及更高版本的模块,此值必须以主版本号结尾,例如
/v2
。
示例
以下示例将 example.com
替换为可以从中下载模块的存储库域。
- v0 或 v1 模块的模块声明
module example.com/mymodule
- v2 模块的模块路径
module example.com/mymodule/v2
注意
模块路径必须唯一标识您的模块。对于大多数模块,路径是 go
命令可以找到代码的 URL(或指向代码的重定向)。对于永远不会直接下载的模块,模块路径可以只是您控制的一些名称,以确保唯一性。前缀 example/
也为类似这些示例的示例保留。
有关更多详细信息,请参阅 管理依赖项。
在实践中,模块路径通常是模块源的存储库域和存储库中模块代码的路径。当下载模块版本以代表模块用户解析依赖项时,go
命令依赖于这种形式。
即使您最初不打算让其他代码使用您的模块,使用其存储库路径也是最佳实践,这将帮助您避免在以后发布模块时不得不重命名它。
如果您最初不知道模块的最终存储库位置,请考虑暂时使用安全的替代方案,例如您拥有的域的名称或您控制的名称(例如您的公司名称),以及从模块的名称或源目录开始的路径。有关更多信息,请参阅 管理依赖项。
例如,如果您在 stringtools
目录中进行开发,您的临时模块路径可能是 <company-name>/stringtools
,如以下示例所示,其中 company-name 是您公司的名称
go mod init <company-name>/stringtools
go
指示该模块是在假设指令指定 Go 版本的语义的情况下编写的。
有关更多信息,请参阅 Go 模块参考中的 go
指令。
语法
go minimum-go-version
- minimum-go-version
- 编译此模块中的包所需的 Go 版本的最小值。
示例
- 模块必须在 Go 版本 1.14 或更高版本上运行
go 1.14
注意
go
指令设置使用此模块所需的 Go 版本的最小值。在 Go 1.21 之前,该指令只是建议性的;现在它是一个强制性要求:Go 工具链拒绝使用声明了较新 Go 版本的模块。
go
指令是选择要运行的 Go 工具链的输入。有关详细信息,请参阅“Go 工具链”。
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/modules.txt
存在且与go.mod
一致,则无需显式使用-mod=vendor
标志。 - 在
go 1.16
或更高版本中,all
包模式仅匹配 主模块 中的包和测试的包所传递导入的包。这是自模块引入以来go mod vendor
保留的相同包集。在较低版本中,all
还包括主模块中包导入的包的测试、这些包的测试,等等。 - 在
go 1.17
或更高版本中go.mod
文件包括为提供主模块中包或测试传递导入的任何包的每个模块的显式require
指令。(在go 1.16
和更低版本中,只有在 最小版本选择 否则会选择不同的版本的情况下,才会包含间接依赖项。)此额外信息允许 模块图修剪 和 延迟模块加载。- 由于间接依赖项可能比之前的
go
版本多很多,因此间接依赖项记录在go.mod
文件中的单独块中。 go mod vendor
会省略供应商依赖项的go.mod
和go.sum
文件。(这允许在vendor
的子目录中调用go
命令来识别正确的主模块。)go mod vendor
会在vendor/modules.txt
中记录每个依赖项的go.mod
文件中的go
版本。
- 在
go 1.21
或更高版本中go
行声明了与该模块一起使用的 Go 版本的最低要求。go
行必须大于或等于所有依赖项的go
行。go
命令不再尝试维护与之前的较旧 Go 版本的兼容性。go
命令在go.sum
文件中保存go.mod
文件的校验和方面更加谨慎。
go.mod
文件最多可以包含一个 go
指令。大多数命令会在不存在 go
指令的情况下添加一个具有当前 Go 版本的 go
指令。
toolchain
声明一个建议的 Go 工具链,与该模块一起使用。只有在该模块为主模块并且默认工具链比建议的工具链旧时才生效。
有关更多信息,请参阅“Go 工具链”和 Go 模块参考中的 toolchain
指令。
语法
toolchain toolchain-name
- toolchain-name
- 建议的 Go 工具链的名称。标准工具链名称采用
goV
的形式,其中 V 是 Go 版本,例如go1.21.0
和go1.18rc1
。特殊值default
会禁用自动工具链切换。
示例
- 建议使用 Go 1.21.0 或更高版本
toolchain go1.21.0
注意
有关 toolchain
行如何影响 Go 工具链选择的详细信息,请参阅“Go 工具链”。
godebug
指示要应用于该模块的主包的默认 GODEBUG 设置。这些设置会覆盖任何工具链默认设置,并且会被主包中的显式 //go:debug
行覆盖。
语法
godebug debug-key=debug-value
- debug-key
- 要应用的设置的名称。可以在 [ GODEBUG 历史记录](https://golang.ac.cn/doc/godebug#history) 中找到设置列表以及它们引入的版本。
- debug-value
- 提供给设置的值。如果未指定,则为
0
表示禁用,1
表示启用命名行为。
示例
- 使用新的 1.23
asynctimerchan=0
行为godebug asynctimerchan=0
- 使用 Go 1.21 的默认 GODEBUG,但使用旧的
panicnil=1
行为godebug ( default=go1.21 panicnil=1 )
注意
GODEBUG 设置仅适用于当前模块中的主包和测试二进制文件的构建。当模块用作依赖项时,它们不会生效。
有关向后兼容性的详细信息,请参阅“Go、向后兼容性和 GODEBUG”。
require
将模块声明为当前模块的依赖项,并指定所需的模块的最小版本。
有关更多信息,请参阅 Go 模块参考中的 require
指令。
语法
require module-path module-version
- module-path
- 模块的模块路径,通常是模块源代码库域名和模块名称的组合。对于模块版本 v2 及更高版本,此值必须以主版本号结尾,例如
/v2
。 - module-version
- 模块的版本。可以是发布版本号,例如 v1.2.3,也可以是 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 会为每个包含导入包的模块插入 require
指令。当模块尚未在其存储库中标记时,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
- 替换模块的版本。仅当替换路径是模块路径(而不是本地目录)时,才允许指定替换版本。
示例
-
用模块存储库的分支替换
在以下示例中,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.3 替换模块版本 v1.2.5。
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
有关使用模块代码的本地副本的更多信息,请参阅 需要本地目录中的模块代码。
注意
当您想要 Go 使用另一个路径查找模块的源代码时,使用 replace
指令临时用另一个值替换模块路径值。这会将 Go 搜索模块的范围重定向到替换位置。您无需更改包导入路径即可使用替换路径。
使用 exclude
和 replace
指令来控制构建当前模块时构建时依赖项解析。这些指令在依赖于当前模块的模块中被忽略。
replace
指令在以下情况下很有用
- 您正在开发一个新的模块,其代码尚未在存储库中。您想用本地版本进行测试。
- 您已识别出依赖项中的问题,已克隆依赖项的存储库,并且您正在使用本地存储库测试修复。
请注意,单独的 replace
指令不会将模块添加到 模块图 中。还需要 require
指令 引用替换的模块版本,无论是在主模块的 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/theirmodule 版本 v1.3.0
exclude example.com/theirmodule v1.3.0
注意
使用 exclude
指令排除间接需要但由于某种原因无法加载的模块的特定版本。例如,您可能会使用它来排除具有无效校验和的模块的版本。
使用 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 // Published accidentally.
-
撤回版本范围
retract [v1.0.0,v1.0.5] // Build broken on some platforms.
注意
使用 retract
指令指示不应使用模块的先前版本。用户不会使用 go get
、go mod tidy
或其他命令自动升级到撤回的版本。用户不会在使用 go list -m -u
时看到撤回的版本作为可用更新。
撤回的版本应保持可用,以便已经依赖它们的用户的能够构建其包。即使从源代码库中删除了撤回的版本,它也可能仍然在镜像(如 proxy.golang.org)上可用。依赖于撤回版本的用户的可能会在运行 go get
或 go list -m -u
时收到相关模块的通知。
go
命令通过读取模块最新版本中 go.mod
文件中的 retract
指令来发现撤回的版本。最新版本按优先级排序为
- 如果有,则为其最高发布版本
- 如果有,则为其最高预发布版本
- 存储库默认分支的顶端的伪版本。
添加撤回时,几乎总是需要标记一个新的、更高的版本,以便命令在模块的最新版本中看到它。
您可以发布一个版本,其唯一目的是发出撤回信号。在这种情况下,新版本也可以撤回自身。
例如,如果您不小心标记了 v1.0.0
,则可以使用以下指令标记 v1.0.1
retract v1.0.0 // Published accidentally.
retract v1.0.1 // Contains retraction only.
不幸的是,一旦发布了一个版本,就无法更改它。如果您后来在不同的提交中标记了 v1.0.0
,则 go
命令可能会检测到 go.sum
或 校验和数据库 中的校验和不匹配。
模块的撤回版本通常不会出现在 go list -m -versions
的输出中,但可以使用 -retracted
来显示它们。有关更多信息,请参阅 Go 模块参考中的 go list -m
。