摘要:工作空间是Go 1.18新添加的特性,英文名叫workspace
,同时还有和工作空间相关的命令go work
。工作空间与Go模块是完全不同的概念。模块是代码组织的一种方式,工作空间本质上是一个目录,它影响的是编译器的工作,只在开发人员的本地发挥作用。工作空间的出现是为了方便多模块开发模式,本文将会介绍任何使用工作空间进行开发。
Go Module的开发模式
从Go1.11开始,Go Module横空出世,让我们摆脱了Go Path,从此代码可以放在任意地方。虽然饱受争议,但也在磕磕盼盼中逐渐被人们接受。由于Go工作空间并不是Go Module的替代之物,所以还是让我们从Go Module开始吧。
首先找一个地方,打开PowerShell,然后依次执行以下命令。
mkdir work
cd work
mkdir hello
mkdir world
cd hello
go mod init github.com/caiwangg/hello
new-item hello.go
cd ../world
go mod init github.com/caiwangg/world
new-item world.go
其实,上面的命令做了这样一件事:创建一个work
文件夹,进入work
文件夹创建hello
和world
两个目录。然后分别在两个目录中初始化Go模块,并分别在两个目录中创建hello.go
和world.go
文件。
这就是一个简单的多模块开发场景,在工作中也很常见,比如我们可能需要同时开发主项目和公共的工具库。作为例子,我们只是模仿这一形式。
接下来用你喜欢的代码编辑器打开hello.go
,输入以下代码。
package hello
func SayHello(name string) string {
return "Hello, " + name + " !"
}
同样,在world.go
中输入以下代码。
package main
import (
"fmt"
"github.com/caiwangg/hello"
)
func main() {
name := "Caiwangg"
fmt.Println(hello.SayHello(name))
}
为了在world
中能够调用hello
模块的函数,我们还需要修改一下world
模块中的go.mod
文件,在文件最后添加以下两行内容。
require github.com/caiwangg/hello v0.1.0
replace github.com/caiwangg/hello v0.1.0 => ../hello
现在切换到world
目录下,执行以下命令运行项目。
PS XXX\work\world> go run .
Hello, Caiwangg !
看到Hello, Caiwangg !
的输出说明我们的项目是正常的。但是这其中有一个小小的问题,我们的代码不可能永远放在本地,不管是hello
模块还是world
模块,它们都有对应的代码仓库,尽管我们的例子中没有显示出这一点。
为了使用本地正在开发的hello
模块,我们不得不在world
模块的go.mod
文件中使用replace
指令。当我们要将world
模块推送到代码仓库时,又必须把replace
去掉。频繁的修改go.mod
文件对我们来说将是一个麻烦。
Go工作空间
我们在上一节中创建的work
目录就是为工作空间做准备的。首先我们在powershell中切换到work
目录,然后执行以下命令:
go work init world hello
以上命令用来初始化工作空间,它会在work
目录下创建一个go.work
文件,命令中的world
和hello
都会出现在go.work
文件的use
模块中。以下就是我们的go.work
文件的内容。
go 1.18
use (
./hello
./world
)
该命令的基本语法是go work init [moddirs]
,如果不提供moddirs
,将会创建一个空的工作空间。工作空间声明了一组模块,同一个工作空间中的模块互相可见,可以直接使用。
工作空间创建以后,还可以通过go work use [-r] moddirs
添加模块,-r
表示递归子目录。当然你也可以直接在代码编辑器中编辑go.work
文件。
现在,我们把之前在world
的go.mod
文件中添加的那两行去掉,也就是将它恢复成如下样子。
module github.com/caiwangg/world
go 1.18
// require github.com/caiwangg/hello v0.1.0
// replace github.com/caiwangg/hello v0.1.0 => ../hello
理论上来说,这时在work
目录下运行go run .\world
是编译不过的,因为找不到hello
模块。但是由于go.work
的存在,神奇的事情发生了,代码成功编译并运行,输出了Hello, Caiwangg !
。
这就是工作空间的魅力,我们不需要replace
指令,也不需要在提交代码时修改go.mod
文件。编译器会自动使用工作空间下的模块,对于多模块同时开发的场景,这简直就是福音。也许在一开始你认为不会多线作战,但是公共模块这个东西往往都是在项目开发过程中被拆分出去的,因为项目架构也是随着开发在变化的。当你在项目开发的中途想拆分模块时,工作空间会让拆分过程更加丝滑无痛。
总结
总结个屁,冲就完了。