教程:多模块工作空间入门

本文翻译自《Tutorial: Getting started with multi-module workspaces》。

目录

先决条件

为代码创建模块

创建工作空间

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

了解有关工作空间的详细信息

本教程介绍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)小节。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注