Go 博客
熟悉工作区
Go 1.18 增加了工作区模式,让您可以同时处理多个模块。
您可以通过访问 下载 页面来获取 Go 1.18。 发行说明 包含所有更改的更多详细信息。
工作区
Go 1.18 中的 工作区 允许您同时处理多个模块,而无需编辑每个模块的 go.mod
文件。工作区内的每个模块在解析依赖项时都会被视为主模块。
以前,要在其中一个模块中添加一个功能并在另一个模块中使用它,您需要发布第一个模块的更改,或者使用 replace
指令 编辑 go.mod 文件以引用您本地的、未发布的模块更改。为了无误地发布,您必须在将本地更改发布到第一个模块后,从依赖模块的 go.mod
文件中删除 replace
指令。
使用 Go 工作区,您可以通过工作区目录根目录中的 go.work
文件来控制所有依赖项。go.work
文件包含 use
和 replace
指令,它们会覆盖单个 go.mod
文件,因此无需单独编辑每个 go.mod
文件。
要创建工作区,请在工作区目录列表上运行 go work init
,并将模块目录作为空格分隔的参数。工作区不需要包含您正在处理的模块。init
命令会创建一个 go.work
文件,其中列出了工作区中的模块。如果您在没有参数的情况下运行 go work init
,该命令将创建一个空工作区。
要将模块添加到工作区,请运行 go work use [moddir]
或手动编辑 go.work
文件。运行 go work use -r .
可以递归地将参数目录中带有 go.mod
文件的目录添加到您的工作区。如果一个目录没有 go.mod
文件,或者不再存在,则该目录的 use
指令将从您的 go.work
文件中移除。
go.work
文件的语法与 go.mod
文件类似,并包含以下指令:
go
:go 工具链版本,例如go 1.18
use
:将磁盘上的模块添加到工作区中的主模块集。其参数是包含模块go.mod
文件的目录的相对路径。use
指令不会添加指定目录子目录中的模块。replace
:与go.mod
文件中的replace
指令类似,go.work
文件中的replace
指令会将模块的 *特定版本* 或 *所有版本* 的内容替换为在其他地方找到的内容。
工作流
工作区非常灵活,支持各种工作流。以下部分将简要概述我们认为最常见的工作流。
向外部模块添加功能并在您自己的模块中使用
-
为您的工作区创建一个目录。
-
克隆您要编辑的外部模块。
-
在外部模块的本地版本中添加您的功能。
-
在工作区文件夹中运行
go work init [path-to-upstream-mod-dir]
。 -
修改您自己的模块,以实现添加到外部模块中的功能。
-
在工作区文件夹中运行
go work use [path-to-your-module]
。go work use
命令将您的模块路径添加到您的go.work
文件中。go 1.18 use ( ./path-to-upstream-mod-dir ./path-to-your-module )
-
运行并测试您模块中使用新添加的外部模块功能。
-
发布带有新功能的外部模块。
-
发布使用新功能的您的模块。
在同一存储库中处理多个相互依赖的模块
在同一存储库中处理多个模块时,go.work
文件定义了工作区,而不是使用每个模块 go.mod
文件中的 replace
指令。
-
为您的工作区创建一个目录。
-
克隆包含您要编辑的模块的存储库。这些模块不必放在您的工作区文件夹中,因为您可以使用
use
指令指定每个模块的相对路径。 -
在您的工作区目录中运行
go work init [path-to-module-one] [path-to-module-two]
。示例:您正在处理
example.com/x/tools/groundhog
,它依赖于example.com/x/tools
模块中的其他包。克隆存储库,然后在您的工作区文件夹中运行
go work init tools tools/groundhog
。您的
go.work
文件的内容如下所示:go 1.18 use ( ./tools ./tools/groundhog )
在
tools
模块中进行的任何本地更改都将由您工作区中的tools/groundhog
使用。
在依赖项配置之间切换
要在不同的依赖项配置下测试您的模块,您可以创建多个具有单独 go.work
文件的工作区,或者保留一个工作区并在单个 go.work
文件中注释掉您不想要的 use
指令。
创建多个工作区
- 为不同的依赖项需求创建单独的目录。
- 在每个工作区目录中运行
go work init
。 - 通过
go work use [path-to-dependency]
在每个目录中添加您想要的依赖项。 - 在每个工作区目录中运行
go run [path-to-your-module]
,以使用其go.work
文件指定的依赖项。
要在同一工作区中测试不同的依赖项,请打开 go.work
文件并添加或注释掉所需的依赖项。
仍在 Gopath 下工作?
也许使用工作区会改变您的想法。GOPATH
用户可以使用位于其 GOPATH
目录根目录下的 go.work
文件来解析其依赖项。工作区并非旨在完全重现所有 GOPATH
工作流,但它们可以创建一个共享 GOPATH
部分便利性,同时仍提供模块优势的设置。
为 GOPATH 创建工作区
- 在您的
GOPATH
目录的根目录下运行go work init
。 - 要在您的工作区中使用本地模块或特定版本作为依赖项,请运行
go work use [path-to-module]
。 - 要替换您模块
go.mod
文件中的现有依赖项,请使用go work replace [path-to-module]
。 - 要添加 GOPATH 或任何目录中的所有模块,请运行
go work use -r
以递归地将带有go.mod
文件的目录添加到您的工作区。如果一个目录没有go.mod
文件,或者不再存在,则该目录的use
指令将从您的go.work
文件中移除。
注意:如果您有不带
go.mod
文件但您想添加到工作区的项目,请进入其项目目录并运行go mod init
,然后使用go work use [path-to-module]
将新模块添加到您的工作区。
工作区命令
除了 go work init
和 go work use
,Go 1.18 还为工作区引入了以下命令:
go work sync
:将go.work
文件中的依赖项推回到每个工作区模块的go.mod
文件中。go work edit
:提供一个命令行接口来编辑go.work
,主要供工具或脚本使用。
模块感知构建命令和一些 go mod
子命令会检查 GOWORK
环境变量,以确定它们是否处于工作区上下文中。
如果 GOWORK
变量指向一个以 .work
结尾的文件路径,则启用工作区模式。要确定正在使用哪个 go.work
文件,请运行 go env GOWORK
。如果 go
命令不在工作区模式下,输出将为空。
启用工作区模式后,将解析 go.work
文件,以确定工作区模式的三个参数:Go 版本、目录列表和替换列表。
一些可以在工作区模式下尝试的命令(前提是您已经知道它们的作用!)
go work init
go work sync
go work use
go list
go build
go test
go run
go vet
编辑器体验改进
我们特别高兴 Go 的语言服务器 gopls 和 VSCode Go 扩展 的升级,它们使得在 LSP 兼容编辑器中处理多个模块的体验流畅且富有成效。
在工作区内的模块之间,查找引用、代码补全和跳转到定义都可以正常工作。gopls
版本 0.8.1 引入了对 go.work
文件的诊断、补全、格式化和悬停功能。您可以利用这些 gopls 功能与任何 LSP 兼容编辑器。
编辑器特定说明
- 最新的 vscode-go 版本 通过 Go 状态栏的快速选择菜单,可以快速访问工作区的
go.work
文件。
- GoLand 支持工作区,并计划为
go.work
文件添加语法高亮和代码补全功能。
有关在不同编辑器中使用 gopls
的更多信息,请参阅 gopls
的 文档。
下一步是什么?
下一篇文章: 何时使用泛型
上一篇文章: Go 如何缓解供应链攻击
博客索引