Go 博客
熟悉工作区
Go 1.18 向 Go 添加了工作区模式,允许您同时处理多个模块。
您可以通过访问下载页面获取 Go 1.18。发行说明中提供了所有更改的更多详细信息。
工作区
Go 1.18 中的工作区允许您同时处理多个模块,而无需为每个模块编辑 go.mod
文件。工作区内的每个模块在解决依赖关系时都被视为主要模块。
以前,要在某个模块中添加一个特性并在另一个模块中使用它,您需要发布第一个模块的更改,或者使用 replace
指令编辑依赖模块的 go.mod 文件,指向您本地未发布的模块更改。为了在发布时不出错,您必须在将本地更改发布到第一个模块后,从依赖模块的 go.mod
文件中移除 replace
指令。
使用 Go 工作区,您可以在工作区目录的根目录下使用 go.work
文件控制所有依赖关系。go.work
文件具有覆盖单个 go.mod
文件的 use
和 replace
指令,因此无需单独编辑每个 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 的编辑器中处理多个模块成为一种顺畅且有益的体验。
查找引用、代码补全和跳转到定义在工作区内的模块之间正常工作。版本 0.8.1 的 gopls
引入了针对 go.work
文件的诊断、补全、格式化和悬停功能。您可以在任何 LSP 兼容的编辑器中利用这些 gopls 特性。
编辑器特定说明
- 最新的 vscode-go 版本允许通过 Go 状态栏的 Quick Pick 菜单快速访问工作区的
go.work
文件。
- GoLand 支持工作区,并计划为
go.work
文件添加语法高亮和代码补全。
有关在不同编辑器中使用 gopls
的更多信息,请参阅 gopls
的文档。
下一步?
下一篇文章:何时使用泛型
上一篇文章:Go 如何缓解供应链攻击
博客索引