教程:开始使用多模块工作区

本教程介绍 Go 中多模块工作区的基础知识。使用多模块工作区,您可以告诉 Go 命令您正在同时在多个模块中编写代码,并轻松地在这些模块中构建和运行代码.

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

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

先决条件

本教程需要 go1.18 或更高版本. Make sure you’ve installed Go at Go 1.18 or later using the links at go.dev/dl.

为您的代码创建一个模块

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

  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 模块的依赖项.

    $ 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

The go work init command tells go to create a go.work file for a workspace containing the modules in the ./hello directory. (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 目录中的模块应该是主模块。

因此,在 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. 克隆仓库

    在工作区目录中,运行 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命令下载的模块缓存中的模块版本.

  3. 添加新函数.

    我们将向golang.org/x/example/stringutil包中添加一个新函数以将字符串变大写。

    workspace/example/stringutil 目录中创建一个名为 toupper.go 的新文件,其中包含以下内容:

    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)
    }
    
  4. 修改hello程序以使用该函数.

    修改 workspace/hello/hello.go 的内容以包含以下内容:

    package main
    
    import (
        "fmt"
    
        "golang.org/x/example/stringutil"
    )
    
    func main() {
        fmt.Println(stringutil.ToUpper("Hello"))
    }
    

在工作区运行代码

从工作区目录,运行

$ 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。这通常是通过在模块的版本控制存储库上标记一个提交来完成的。有关更多详细信息,请参阅模块模块发布工作流文档。发布完成后,我们可以在 hello/go.mod中增加对 golang.org/x/example 模块的要求( increase the requirement):

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

这样, go命令可以正确解析工作区之外的模块.

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

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

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