该教程介绍 Go 多模块工作区的基础。使用多模块工作区,可以告诉 Go 命令我们同时在多个模块中编写代码,并且可以很容易地构建和运行多个模块中的代码。
本教程将在共享的多模块工作区创建 2 个模块,以及对这些模块进行更改,并且在构建中查看更改结果。
该教程依赖 Go 1.18+。请确保已经安装 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,克隆存储库
在工作空间目录,运行 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 存储库被检出到 ./example
。golang.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/reverse
包的 golang.org/x/example/hello
模块。
这将允许使用将在 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))
}
在工作空间目录运行
$ 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]
为 dir
向 go.work
文件中添加 use
指令,如果参数目录不存在,那么删除该 use
目录。-r
标记递归地检查 dir
的子目录。go work edit
编辑 go.work
文件,与 go mod edit
类似。go work sync
将工作区构建列表中的依赖项同步到每个工作区模块中。