[官文翻译]golang指南:创建多模块工作区

242 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情


本文翻译自:
Tutorial: Getting started with multi-module workspaces - The Go Programming Language

指南:创建多模块工作区

内容

该教程介绍了 go 中多模块工作区的基础。在多模块工作区中,可以告诉 go 命令你是同时在多模块中编写代码,并且可以更容易地在这些模块中编译和运行代码。

在该教程中,可以在共享的多模块工作区创建两个模块,然后跨这些模块进行改动,然后在编译中看一下这些改动的结果。

注意:  其它的指南参考 指南.

前提

  • 安装 Go 1.8 或更高版本。
  • 编辑代码的工具。  平时使用的任何文本编辑器都可以。
  • 一个命令终端  Go 在 Liunx 或 Mac 的任何终端上在 Windows 上的 PowerShell 或 cmd 上都能正常使用。

该指南需要 go1.18 或更高版本。确保已经按照链接 go.dev/dl 的内容安装了 Go 1.8或更高版本。

为代码创建模块

首先,为要编写的代码创建模块。

  1. 打开终端命令行,进入到 home 目录。

    在 Linux 或 Mac 上:

    $ cd
    

    在 Windows 上:

    C:> cd %HOMEPATH%
    

    下面的内容会显示 $ 作为提示符。你使用的命令在 Windows 上也能正常工作。

  2. 在命令行,为代码创建工作区。

    $ 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

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 目录中的模块应该作为 main (主)模块。

所以 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 将参数中所有的 UTF8字符转为大写。
    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 模块的引入:

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

这样, go 命令就可以正确地在工作区外解析模块了。

学习关于工作区的更多内容

在上面指南中看到的 go work init 命令之外 ,go 命令还有一些用于工作区的子命令:

  • go work use [-r] [dir] 如果 dir 目录已经存在,则向 go.work 文件中添加一个 use 指令使用 dir,如果参数的目录不存在,则会移除对目录的 use-r 标志表示会递归检查 dir 的子目录。
  • go work edit 用来编辑 go.work 文件,类似于 go mod edit
  • go work sync 同步工作区的编译列表依赖到每个工作区模块中。

更多关于工作和 go.work 文件的详细内容,请查看 Go 模块引用中 工作区 。