一起养成写作习惯!这是我参与「掘金日新计划 · 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或更高版本。
为代码创建模块
首先,为要编写的代码创建模块。
-
打开终端命令行,进入到 home 目录。
在 Linux 或 Mac 上:
$ cd在 Windows 上:
C:> cd %HOMEPATH%下面的内容会显示 $ 作为提示符。你使用的命令在 Windows 上也能正常工作。
-
在命令行,为代码创建工作区。
$ mkdir workspace $ cd workspace -
初始化模块
我们会创建一个新模块
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 程序中使用。
-
克隆仓库
在工作区目录,运行
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. -
添加模块到工作区中
$ go work use ./examplego work use命令会向 go.work 文件中添加一个新模块。现在它看上去如下:go 1.18 use ( ./hello ./example )该模块现在同时包含了
example.com/hello模块和golang.org/x/example模块。这会允许我们使用后面在
stringutil模块副本中编写的新代码来代替使用go get下载的模块缓存中的模块版本。 -
添加新函数。
我们会向
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) } -
修改 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 模块引用中 工作区 。