- 本教程介绍Go中多模块工作区的基础知识。使用多模块工作区,您可以告诉Go命令您正在同时在多个模块中编写代码,并轻松地在这些模块中构建和运行代码。
- 在本教程中,您将在共享的多模块工作区中创建两个模块,对这些模块进行更改,并在构建中查看这些更改的结果。
- 必须条件:
- Go 1.18或更高版本的安装。
- 用于编辑代码的工具。 您拥有的任何文本编辑器都可以正常工作。
- 一个命令终端。Go在Linux和Mac上的任何终端以及Windows中的PowerShell或cmd上都能很好地工作。
- 本教程需要go1.18或更高版本。 使用go.dev/dl中的链接,确保您已在Go 1.18或更高版本中安装了Go。
创建一个模块#
- 首先,为您要编写的代码创建一个模块。
- 打开命令提示符并切换到您的主目录。
- 在Linux或Mac上:
cd
。
- 在Windows上:
C:\> cd %HOMEPATH%
。
- 本教程的其余部分将显示$作为提示。您使用的命令也可以在Windows上运行。
- 在命令提示符下,为您的代码创建一个名为工作区的目录。
1
2
|
$ mkdir workspace
$ cd workspace
|
初始化模块
- 我们的示例将创建一个
hello
依赖于golang.org/x/example模块的新模块。
- 创建hello模块:
1
2
3
4
|
$ 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模块的依赖(如果有需要)。
1
2
3
|
$ go get golang.org/x/example
go: downloading golang.org/x/example v0.0.0-20220304235025-ad95e7f791d8
go get: added golang.org/x/example v0.0.0-20220304235025-ad95e7f791d8
|
- 在hello目录下创建hello.go,内容如下:
1
2
3
4
5
6
7
8
9
10
11
|
package main
import (
"fmt"
"golang.org/x/example/stringutil"
)
func main() {
fmt.Println(stringutil.Reverse("Hello"))
}
|
- 现在,运行hello程序:
1
2
3
|
$ go mod tidy
$ go run .
olleH
|
- 目录结构为:
1
2
3
4
|
|--workspace
|----hello
|------hello.go
|------go.mod
|
创建工作区#
- 在这一步中,我们将创建一个
go.work
文件来指定模块的工作区。
初始化工作区#
- 在
workspace
目录中,运行:
1
2
3
|
# go1.18beta2.exe work init ./hello ## 本地用的go1.18beta2版本
# 当前目录是 hello 的上级目录下,执行完go work init后会生成一个go.work文件
$ 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.mod文件中的go指令。
- use指令告诉Go在构建时hello目录中的模块应该是主模块。
- 因此,在工作区的任何子目录中,该模块都将处于活动状态。
- 目录结构为:
1
2
3
4
5
|
|--workspace
|----hello
|------hello.go
|------go.mod
|----go.work
|
运行工作区下的目录#
- 在
workspace
目录中,运行:
1
2
3
|
# go1.18beta2.exe run example.com/hello
$ 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程序中使用的新函数。
- 克隆存储库,在
workspace
目录中,运行git命令来克隆存储库:
1
2
3
4
5
6
7
8
|
$ git clone https://github.com/golang/example
Cloning into 'example'...
remote: Enumerating objects: 182, done.
remote: Counting objects: 100% (30/30), done.
remote: Compressing objects: 100% (20/20), done.
remote: Total 182 (delta 6), reused 16 (delta 4), pack-reused 152R
Receiving objects: 100% (182/182), 138.39 KiB | 1.05 MiB/s, done.
Resolving deltas: 100% (74/74), done.
|
- 将模块添加到工作区。
1
2
|
# go1.18beta2.exe work use ./example
$ go work use ./example
|
- go work use命令将一个新模块添加到go.work文件中。它现在看起来像这样:
go 1.18
use (
./hello
./example
)
- 目录结构:
1
2
3
4
5
6
7
8
|
|--workspace
|----hello
|------hello.go
|------go.mod
|----example
|------stringutil
|--------reverse.go
|----go.work
|
- 该模块现在包括example.com/hello模块和golang.org/x/example模块。
- 这将允许我们使用我们将在stringutil模块的副本中编写的新代码,而不是使用go get命令下载的模块缓存中的模块版本。
- 添加新功能:
- 我们将在golang.org/x/example/stringutil包中添加一个将字符串大写的新函数。
- 将新文件夹添加到包含以下内容的workspace/example/stringutil目录:并命令为upper.go文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package stringutil
import "unicode"
// ToUpper uppercases all the runes in its argument string.
func ToUpper(s string) string {
r := []rune(s)
for i := range r {
r[i] = unicode.ToUpper(r[i])
}
return string(r)
}
|
- 修改hello程序以使用该功能,修改workspace/hello/hello.go的内容,包含以下内容:
1
2
3
4
5
6
7
8
9
10
11
|
package main
import (
"fmt"
"golang.org/x/example/stringutil"
)
func main() {
fmt.Println(stringutil.ToUpper("Hello"))
}
|
运行workspace
目录下代码#
- 从workspace目录,运行:
1
2
|
# go1.18beta2.exe run example.com/hello
$ go run example.com/hello
|
- Go命令在go.work文件指定的hello目录中查找命令行中指定的example.com/hello模块,同样使用go.work文件解析golang.org/x/example导入。
- 可以使用go.work而不是添加替换指令来跨多个模块工作。
- 由于这两个模块位于同一个工作区中,因此很容易在一个模块中进行更改并在另一个模块中使用它。