教程:多模块工作区入门

本教程将介绍 Go 中多模块工作区的基本概念。通过多模块工作区,您可以告诉 Go 命令您正在同时编写多个模块的代码,并轻松构建和运行这些模块中的代码。

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

注意: 有关其他教程,请参阅教程

先决条件

  • 安装 Go 1.18 或更高版本。
  • 一个代码编辑工具。 任何文本编辑器都可以。
  • 命令终端。 Go 在 Linux 和 Mac 上的任何终端以及 Windows 上的 PowerShell 或 cmd 中都能很好地工作。

本教程需要 Go 1.18 或更高版本。请确保您已按照 go.dev/dl 上的链接安装了 Go 1.18 或更高版本。

为您的代码创建模块

首先,为您将要编写的代码创建一个模块。

  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
    

创建工作区

在此步骤中,我们将创建一个 go.work 文件来指定一个包含该模块的工作区。

初始化工作区

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 的任何子目录中,该模块都将处于活动状态。

在工作区目录中运行程序

workspace 目录中,运行

$ go run ./hello
olleH

Go 命令将工作区中的所有模块都包含为主模块。这允许我们在模块外部引用模块中的包。在模块或工作区外部运行 go run 命令将导致错误,因为 go 命令不知道使用哪些模块。

接下来,我们将把 golang.org/x/example/hello 模块的本地副本添加到工作区。该模块存储在 go.googlesource.com/example Git 存储库的一个子目录中。然后,我们将向 reverse 包添加一个新函数,我们可以使用它而不是 String

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

在此步骤中,我们将下载包含 golang.org/x/example/hello 模块的 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. 将模块添加到工作区

    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 模块,后者提供了 golang.org/x/example/hello/reverse 包。

    这将允许我们使用我们将在 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))
    }
    

在工作区中运行代码

在 workspace 目录中,运行

$ go run ./hello
olleH 10642

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

go.work 可用于替代添加 replace 指令来处理多个模块。

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

后续步骤

现在,要正确发布这些模块,我们需要发布 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 命令就可以正确地解析工作区外部的模块。

了解更多关于工作区的信息

除了我们在教程前面看到的 go work init 之外,go 命令还有几个用于处理工作区的子命令

  • go work use [-r] [dir]use 指令添加到 go.work 文件中 dir(如果存在),如果参数目录不存在,则删除 use 目录。-r 标志递归地检查 dir 的子目录。
  • go work edit 类似地编辑 go.work 文件,就像 go mod edit 一样
  • go work sync 将工作区的构建列表中的依赖项同步到工作区的每个模块中。

有关工作区和 go.work 文件的更多详细信息,请参阅 Go 模块参考中的 工作区