本文翻译自《Tutorial: Getting started with multi-module workspaces》。
目录
本教程介绍Go中多模块工作空间的基础知识。使用多模块工作空间,你可以告诉Go命令,你正在同时在多个模块中编写代码,并且可以轻松地在这些模块中构建和运行代码。
在本教程中,你将在共享的多模块工作空间中创建两个模块,对这些模块进行更改,并在一个构建中查看这些更改的结果。
注意:有关其他教程,请参见教程。
先决条件
- 安装Go 1.18或更高版本。
- 编辑代码的工具。任何文本编辑器都可以正常工作。
- 命令行终端。Go在Linux和Mac上的任何终端以及Windows中的PowerShell或cmd上都能很好地工作。
本教程需要go1.18或更高版本。确保你已经使用Go.dev/dl上的链接安装了Go 1.18或更高版本。
为你的代码创建一个模块
首先,为你要编写的代码创建一个模块。
1 打开命令提示符并切换到你的家目录。 在Linux或Mac上:
$ cd ~
在Windows上:
C:\> cd %HOMEPATH%
(译者注:或者执行C:\> cd %USERPROFILE%
)
本教程的其余部分将显示$作为提示符。你使用的命令也可以在Windows上使用。
2 在命令提示符下,为代码创建一个名为workspace的目录。
$ mkdir workspace
$ cd workspace
3 初始化模块
我们的示例将创建一个依赖于golang.org/x/example的新模块hello
。
创建hello
模块:
$ mkdir hello
$ cd hello
$ go mod init example.com/hello
go: creating new go.mod: module example.com/hello
使用go get
添加golang.org/x/example依赖项。
$ go get golang.org/x/example
在hello目录中创建hello.go,并输入以下内容:
package main
import (
"fmt"
"golang.org/x/example/stringutil"
)
func main() {
fmt.Println(stringutil.Reverse("Hello"))
}
现在,运行hello程序:
$ go run example.com/hello
olleH
创建工作空间
在这一步中,我们将创建一个go.work文件来指定带有模块的工作空间。
初始化工作空间
在workspace
目录中,运行:
$ go work init ./hello
go work init
命令告诉go
为包含./hello
目录中的模块的工作空间创建一个go.work
文件。
go
命令生成一个如下所示的go.work
文件:
go 1.18
use ./hello
go.work
文件的语法与go.mod
相似。
go
指令告诉Go应该使用哪个版本的Go来解释Go文件。它类似于go.mod
文件中的go
指令。
use
指令告诉Go在构建时hello
目录中的模块应该是主(main)模块。
因此,在workspace
的任何子目录中,该模块都将处于活动状态。
运行workspace目录下的程序
在workspace目录中,运行:
$ go run example.com/hello
olleH
Go命令把包含在工作空间中的所有模块作为主模块。这允许我们引用一个模块中的包,甚至模块外的包。在模块或工作空间之外运行go run
命令会导致错误,因为go
命令不知道要使用哪些模块。
接下来,我们将golang.org/x/example
模块的本地副本添加到工作空间。然后,我们将向stringutil
包添加一个新函数,我们可以使用它来代替Reverse
。
下载并修改golang.org/x/example
模块
在这一步中,我们将下载包含golang.org/x/example
模块的Git存储库的副本,将其添加到工作空间,然后向其中添加一个我们将在hello程序中使用的新函数。
1 克隆存储库 在workspace目录中,运行git
命令来克隆存储库:
$ git clone https://go.googlesource.com/example
Cloning into 'example'...
remote: Total 165 (delta 27), reused 165 (delta 27)
Receiving objects: 100% (165/165), 434.18 KiB | 1022.00 KiB/s, done.
Resolving deltas: 100% (27/27), done.
2 将模块添加到工作空间
$ go work use ./example
go work use
命令将一个新模块添加到go.work文件中。它现在看起来像这样:
go 1.18
use (
./hello
./example
)
该模块现在包括example.com/hello
模块和golang.org/x/example
模块。
这将允许我们使用我们将在stringutil
模块的副本中编写的新代码,而不是使用go get
命令下载的模块缓存中的该模块版本。(译者注:这说明go.work文件中use
的模块被使用的优先级高于本地模块缓存中和网络上的同名模块。)
3 添加新函数
我们将在golang.org/x/example/stringutil
包中添加一个将字符串大写的新函数。
在workspace/example/stringutil
目录中创建一个名为toupper.go
的新文件,其中包含以下内容:
package stringutil
import "unicode"
// ToUpper把参数字符串s里的所有rune字符变为大写
func ToUpper(s string) string {
r := []rune(s)
for i := range r {
r[i] = unicode.ToUpper(r[i])
}
return string(r)
}
4 修改hello程序以使用该函数
修改workspace/hello/hello.go
的内容,包含以下内容:
package main
import (
"fmt"
"golang.org/x/example/stringutil"
)
func main() {
fmt.Println(stringutil.ToUpper("Hello"))
}
运行工作空间里的代码
在workspace目录里,运行
$ go run example.com/hello
HELLO
Go命令找到在命令行上给出的,由go.work
文件指定的,在hello
目录中的example.com/hello
模块。并类似地解析由go.work
文件导入的golang.org/x/example
模块。
可以使用go.work
来代替添加replace
指令跨多个模块工作。
由于这两个模块位于同一个工作空间中,因此很容易在一个模块中进行更改并在另一个模块中使用它。
更进一步
现在,要正确发布这些模块,我们需要发布golang.org/x/example
模块,例如v0.1.0
。 这通常是通过在模块的版本控制存储库里给提交(commit)加标签来完成的。
有关更多详细信息,请参阅模块发布工作流程文档。发布完成后,我们可以在hello/go.mod
中增加对golang.org/x/example
模块的需求:
cd hello
go get golang.org/x/[email protected]
这样,go
命令就可以正确地解析工作空间之外的模块。
学习更多工作空间相关的知识
go
命令除了我们之前在教程中见过的go work init
之外,还有多个子命令用于处理工作空间:
go work use [-r] [dir]
为dir
添加一个use
指令到go.work
文件,如果dir
参数指定的目录存在的话,如果dir
参数指定的目录不存在,该命令就会删除对应的use
指令。dir
的工作文件(如果存在),如果参数目录不存在,则删除use
目录。-r
标志递归地检查dir
参数指定的目录的子目录。go work edit
编辑go.work
文件,类似于go mod edit
。go work sync
将工作空间构建列表中的依赖项同步到每个工作空间模块中。
有关工作空间和go.work
文件的详细信息,请参见《Go模块文档》中的工作空间(workspace)小节。