当一个项目越来越复杂的时候,一定会拆分为多个模块,以便进行代码复用和更好的多人协作开发。

假设我们已经有了两个模块 flysnow.org/utilflysnow.org/product ,模块flysnow.org/product依赖 flysnow.org/util

现在有一个需求,需要同时修改这两个模块,以便让flysnow.org/util新增的方法给模块flysnow.org/product使用。

但是当同事A在模块flysnow.org/util中增加新的方法后,要么推送到VCS中,让负责模块flysnow.org/product的同事B使用,这是发布的场景。

如果模块flysnow.org/util没有发布呢?那么就只能通过go.mod中的replace指令进行替换,把对模块flysnow.org/util的引用,换成本地的未发布的版本,比如:

1
replace flysnow.org/util => /Users/flysnow/go/demo/util

相信我们都遇到过以上两种情形,这两种情形都有相应的弊端,比如:

  1. 把没有调试、没有测试的代码发布了,会影响其他正常构建
  2. replace的时候,忘记改回来,提交到VCS中了,影响了其他人使用

为了解决以上问题,Go 团队提出了工作区的概念,并且在Go 1.18 中发布。

Go 工作区,是你的工作区,它和多人协作、VCS等无关。说白了它就是个本地目录,通过go.work文件来管理多个go.mod模块。

要创建一个Go 工作区非常简单,通过如下命令即可:

1
2
3
mkdir workspace
cd workspace
go work init /Users/flysnow/go/demo/util /Users/flysnow/go/demo/product

在以上示例中,workspace是我创建的一个工作区,可以在你的电脑的任何地方,名字也可以自取。

然后go work init 后是两个go.mod的绝对路径,用空格分开,当然你也可以用相对路径。

运行以上代码后,就会在workspace目录下生成一个go.work文件,它的内容如下:

1
2
3
4
5
6
go 1.18

use (
  /Users/flysnow/go/demo/product
  /Users/flysnow/go/demo/util
)

usego.work文件的一个指令,用于管理包含的go.mod模块。

除了use指令,go.work还有replace指令,它和go.mod的replace很像,它用于把Go 工作区间管理的go.mod全部替换为指定的路径,并且它的优先级要比go.mod的replace要高。

现在,我们用到的这两个模块都在同一个工作区了,那么就不需要再修改模块flysnow.org/product的go.mod replace 指令完成本地的依赖了。

这时候,在工作区 workspce目录下,运行如下命令,即可进行验证。

1
2
➜  workspace go run flysnow.org/product
你好

因为都在一个工作区,go可以帮你找到模块flysnow.org/product所依赖的flysnow.org/util模块。

如果你只是切换到product目录下运行以上命令,只会提示你:

1
2
3
➜  product go run main.go 
main.go:3:8: no required module provides package flysnow.org/util; to add it:
  go get flysnow.org/util

不止我上面这种依赖上游模块的例子可以使用Go工作区,如果你一个代码库中有多个模块也是可以用的,只需要把他们都加入到Go 工作区即可。

go work命令有一个use可以把本地目录的模块加入工作区,如下所示:

1
go work use [path-to-your-module]

方括号中的路径,可以换成你自己电脑上的本地模块路径。

当然你也可以直接修改go.work文件,效果是一样的,这里不再举例,你可以自己试试。

go.work本质上是一种本地化的解决办法,因为go.mod都是放在VCS中的,和项目息息相关,所以我们很少去修改它来达到一些Hack的操作。

现在有了go.work就好办多了,因为它就是一个本地的东西,不在VCS中,想怎么改就怎么改,又不会动到所管理模块的go.mod,所以就不会影响其他协作的开发人员,非常安全。

本文为原创文章,转载注明出处,欢迎扫码关注公众号flysnow_org或者网站 https://www.flysnow.org/ ,第一时间看后续精彩文章。觉得好的话,请猛击文章右下角「在看」,感谢支持。

扫码关注