Go Workspace 简介
在 Go 1.18 发布之后,新增了一个功能,Go workspace。以下是对这个功能的简单介绍。
为什么需要 go workspace
在 Go 1.18 之前的版本,如果你想引用另外一个本地 module A,有两种方法
- 将要引用的那个 module push
- 在当前项目中,用 replace 来指定引用的 module 为本地路径
这样做会带来一些问题
- 某些情况下,你无法 push 代码到远程仓库,这样上面的方法 1 就无法使用了
- 当你使用方法2的时候,需要手动去修改 go.mod 文件,添加 replace。而当 module A 被 push 之后,你还要记得把当前项目的 go.mod 文件中的 replace 去掉。
是不是感觉很麻烦?并且好多操作是需要人去确认的,不仅不适合自动化也容易出错。Go 1.18 推出的 workspace 功能,就很好的解决了这个问题。
一个简单的场景介绍
你在开发一个项目,需要用到其他人的 module,你需要在他的 module 上新增一些功能,以便于你正在开发的项目能用到。
比如你用到了 golang.org/x/example/stringutil,这个里面目前只有一个 Reverse
函数用来反转字符串。你需要在这个 module 上新增一个 Upper
函数用来将字符串转换为全部大写。
- 新建文件夹 workspace-tour,用来做 workspace
- 进入 workspace 目录,clone
golang.org/x/example
的代码。 - 进入 example 目录,也就是我们依赖的 module 的目录。在
stringutil/reverse.go
中新增一个函数Upper
- 进入 workspace 目录,创建你的项目,如
mkdir workspace-tour/my-project cd my-project go mod init github.com/wilkice/workspace-tour
- 我们这边就只创建一个最简单的
main.go
文件,文件内容如下package main import ( "fmt" "golang.org/x/example/stringutil" ) func main() { fmt.Println(stringutil.Upper("hello, world")) }
- 接下来我们进入到
workspace-tour
目录,执行go work use ./example ./my-project
初始化 worksapce,执行完成会在此目录下生成一个go.work
文件。你如果查看这个文件的话,会发现它和go.mod
十分相似。 - 好了,现在我们可以直接进入 my-project 目录,执行
go run main.go
就可以看到我们新增的函数被调用了。不用修改go.mod
,是不是很方便? - 假如你使用这个
Upper
函数之后觉得很好用,于是提了一个 PR,人家也接受了。因为后面可能会用到golang.org/x/example
的其他函数,你准备不用你本地的那个clone 的 example代码了。这个时候,只需要把go.work
文件删除或者从go.work
里面移除example
这个目录。当你下次在my-project
目录下执行go run main.go
,就会使用golang.org/x/example
而不会使用你本地的了。
总结
应用场景
在我看来,目前主要有两个应用场景
- 本地离线开发。有些 module 因为某些原因,不能 push 到任何仓库上,那么用 workspace 就会方便很多。因为你不用每做一个项目,就去手动修改
go.mod
了。你只需要在新建一个目录,把离线的这个 repo 放在这里。有新的项目需要用到这个 module 的时候,就在这个目录下建新的项目。 - 你fork 了一份别人的 module,然后在上面新增了某个功能。之所以这里能用上 workspace 是因为你新增的这个功能如果在原 module 上有了实现(比如你提了一个 PR),那么你可以很快的切换过去,只需要把 go.work 删除就可以了。
参考资料
Get familiar with workspaces - The Go Programming Language Tutorial: Getting started with multi-module workspaces