Go 1.18 提供了 multi-module workspaces(多模块工作区)这样一个非常实用的新功能,接下来就看下这个新功能的使用场景和使用方法。一、先看一个问题 先说一个一直令我比较头疼的问题。平常维护开源项目时,更新的代码提交到 github 之前需要做充分的测试,测试的时候需要将引用 github 的包使用 replace 替换为本地刚开发好的包。假如测试使用的项目叫做 blog ,需要被测试的开源项目名称叫 gocore,假如 blog 项目正常使用 gocore 里面封装的 prometheus 监控功能,blog/main.go 示例代码如下package main import ( "github.com/gin-gonic/gin" "github.com/sunmi-OS/gocore/v2/lib/prometheus" ) func main() { r := gin.Default() p := prometheus.NewPrometheus("app") p.Use(r) r.Run(":80") } blog/go.modmodule blog go 1.18 require ( github.com/gin-gonic/gin v1.8.2 github.com/sunmi-OS/gocore/v2 v2.1.6 ) 如果我要测试本地刚更修改的 gocore 的话,需要更改 blog/go.mod ,使用 replace 将 gocore 包替换为本地的,如下:module blog go 1.18 replace github.com/sunmi-OS/gocore/v2 v2.1.6 => /Users/luduoxin/project/go/gocore require ( github.com/gin-gonic/gin v1.8.2 github.com/sunmi-OS/gocore/v2 v2.1.6 ) 这样虽然能做本地测试,但有一个非常严重的问题,就是代码侵入性太强。这样改了 blog/go.mod 之后,如果提交到代码仓库,别人拉取下来这些代码后是不能直接运行的。二、使用 multi-module workspaces 解决问题 Go 1.18 的发布带来了福音, Go 1.18 提供的 multi-module workspaces 完美得解决了这个问题,接下来我们看使用 multi-module workspaces 是如何解决这个问题的。 首先初始化 workspace,在 blog 项目的父目录(或者新建一个文件夹 workspace,名称可以自取,然后将 blog项目移入此文件夹)打开终端执行如下命令$ go work init ./blog work init 命令会创建一个含有 go.work 文件的工作区,共有包含 ./blog 目录在内的一个模块,go.work 内容如下: go 1.18 use ./blog go.work 文件内容格式和 go.mod 类似,接下来将 gocore 也添加进来作为一个模块,执行如下命令: $ go work use /Users/luduoxin/project/go/gocore 现在 go.work 文件内容如下: go 1.18 use ( ./blog /Users/luduoxin/project/go/gocore ) 这时候,blog 项目引用的 gocore 就是本地的 gocore 代码了。去修改下 gocore 项目下的 /lib/prometheus/prometheus.go 文件的代码来看下效果,在 NewPrometheus 方法起始处添加标准输出代码,如下:fmt.Println("================") fmt.Println("生效了!") fmt.Println("================") 然后到 blog 项目目录下面运行项目看下效果$ go run main.go 会发现控制台的输出里面出现了新添加的代码执行的效果================ 生效了! ================ 可以就看出,blog 项目没有任何改动,不像之前需要在 go.mod 文件添加 replace 语句。三、小节 当本地有很多 module 且这些 module 间存在相互依赖,那么就可以在这些 module 的外面建立一个 Go 工作区,基于这个 Go 工作区,开发与调试这些 module 就会变得非常方便。 文中的代码演示是可以运行起来的,大家可以亲自操作一遍,体会下 multi-module workspaces 的妙处。