1. Go Workspace 介绍

该教程介绍 Go 多模块工作区的基础。使用多模块工作区,可以告诉 Go 命令我们同时在多个模块中编写代码,并且可以很容易地构建和运行多个模块中的代码。

本教程将在共享的多模块工作区创建 2 个模块,以及对这些模块进行更改,并且在构建中查看更改结果。

1.1. 先决条件

该教程依赖 Go 1.18+。请确保已经安装 Go 1.18+。

1.2. 创建模块

为将要编写的代码创建模块。

1,打开命令行提示符,并且切换到主目录。

在 Linux 或 Mac 上:

$ cd

在 Windows 上:

C:\> cd %HOMEPATH%

下面将使用 $ 作为命令提示符。这些命令同样适用于 Windows 系统。

2,通过命令行创建名为“workspace”的目录。

$ mkdir workspace
$ cd workspace

3,初始化模块。

该示例将创建新模块 hello,它依赖 golang.org/x/example 模块。

创建 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/hello/reverse

$ go get golang.org/x/example/hello/reverse

在 hello 目录下创建 hello.go,内容如下:

package main

import (
    "fmt"

    "golang.org/x/example/hello/reverse"
)

func main() {
    fmt.Println(reverse.String("Hello"))
}

运行 hello 程序:

$ go run .
olleH

1.3. 创建工作区

下面创建 go.work 文件,指定包含模块的工作区。

1.3.1. 初始化工作区

workspace 目录下执行:

go work init ./hello

go work init 告诉 go 为工作空间创建 go.work 文件,该工作空间当前包含 ./hello 目录中的模块。

go 命令生成的 go.work 文件如下所示:

go 1.18

use ./hello

go.work 文件的语法与 go.mod 相似。

go 指令告诉 Go,应该使用哪个版本的 Go 解释该文件内。与 go.mod 文件中的 go 指令类似。

use 指令告诉 Go,在进行构建时,hello 目录中的模块应该是主模块。

因此,在 workspace 的任何子目录中,该模块都处于活跃状态。

1.3.2. 运行 workspace 目录中的程序

workspace 目录中,运行:

$ go run ./hello
olleH

Go 命令将工作空间中的所有模块当作主模块。这允许在模块内甚至模块外引用包。在模块或工作空间外,运行 go run 命令将导致错误,因为 go 命令不知道使用哪个模块。

下面,向工作空间添加 golang.org/x/example/hello 模块的本地拷贝。该模块位于 go.googlesource.com/example Git 存储库的子目录中。然后,向 reverse 包添加用于替代 String 的新函数。

1.4. 下载及修改 golang.org/x/example/hello 模块

该步骤将下载包含 golang.org/x/example/hello 模块的 Git 存储库副本,并且将其添加到工作空间中,然后向其中添加将在 hello 程序中使用的新函数。

1,克隆存储库

在工作空间目录,运行 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,将该模块添加到工作空间

Git 存储库被检出到 ./examplegolang.org/x/example/hello 模块的源代码在 ./example/hello。将其添加到工作空间:

$ go work use ./example/hello

go work use 命令将新模块添加到 go.work 文件。它现在看起来是这样的:

go 1.18

use (
    ./hello
    ./example/hello
)

该工作空间现在包含 example.com/hello 模块,以及提供 golang.org/x/example/hello/reverse 包的 golang.org/x/example/hello 模块。

这将允许使用将在 reverse 包的副本中编写的新代码,而非使用 go get 命令下载的模块缓存中的包版本。

3,添加新函数

下面将向 golang.org/x/example/hello/reverse 包添加反转数字的新函数。

workspace/example/hello/reverse 目录中,创建名为 int.go 的新文件,内容如下:

package reverse

import "strconv"

// Int returns the decimal reversal of the integer i.
func Int(i int) int {
    i, _ = strconv.Atoi(String(strconv.Itoa(i)))
    return i
}

4,修改 hello 程序,使用该函数

修改 workspace/hello/hello.go 的内容,使其包含如下内容:

package main

import (
    "fmt"

    "golang.org/x/example/hello/reverse"
)

func main() {
    fmt.Println(reverse.String("Hello"), reverse.Int(24601))
}

1.4.1. 在工作空间中运行代码

在工作空间目录运行

$ go run ./hello
olleH 10642

Go 命令在 go.work 文件指定的 hello 目录中查找命令行中指定的 example.com/hello 模块。类似地,使用 go.work 文件解析 golang.org/x/example/hello/reverse 导入。

go.work 可以用于替代添加 replace 指令。

由于这两个模块位于同一个工作区中,因此可以很容易地在一个模块中进行更改,在另一个模块中使用。

1.4.2. 更进一步

为正确地发布这些模块,需要发布 golang.org/x/example/hello 模块,比如 v0.1.0。通常通过在模块的版本控制库中为提交打标签的方式,实现此目标。请参阅模块发布工作流文档,获取详情。发布完成后,可以在 hello/go.mod 中增加对 golang.org/x/example/hello 模块的依赖:

cd hello
go get golang.org/x/example/hello@v0.1.0

这样,go 命令可以正确解析工作空间之外的模块。

1.5. 了解更多关于工作空间信息

除前面提到的 go work init 外,go 命令还有多个用于处理工作区的子命令:


参考文档