go.work工作区
教程:多模块工作区入门 - Go 编程语言 - Go 编程语言
Go 1.18 引入。
工作区的作用是在一个“大工程”中,同时管理多个“子工程”,且这几个“子工程”之间可以方便地直接相互引用,而不再查找远程仓库的同名依赖(replace指令)。可见工作区本身属于临时开发配置,不属于发布配置。
使用
一般情况(个人小项目、团队内没有同时负责多个工程)下是用不到工作区的,用到工作区的情况都是一个人同时要维护多个工程,此时对工程在本地修改后,代码合入前,这些修改无法从远程仓库拉取得到(因为都在本地),因此需要让其他依赖此工程的工程,使用replace指令来将其依赖重定向到本地的版本。而工作区就是方便管理这些replace指令的。
在Go 1.18以前,如果遇到以下场景:Module A新增了一个feature,Module B需要使用Module A的这个新feature,你有2种方案:
- 发布Module A的修改到代码仓库,Module B更新依赖的Module A的版本即可
- 修改Module B的
go.mod
,使用replace
指令把对Module A的依赖指向你本地未发布的Module A所在目录。等Module A发布后,在发布Module B的时候,再删除Module B的go.mod
文件里的replace
指令。有了Go工作区模式之后,针对上述场景,我们有了更为简单的方案:你可以在工作区目录维护一个
go.work
文件来管理你的所有依赖。go.work
里的use
和replace
指令会覆盖工作区目录下的每个Go Module的go.mod
文件,因此没有必要去修改Go Module的go.mod
文件了。
注意:
- 工作区只能用于使用Go Modules管理的工程
- 通常情况下, 建议不要提交
go.work
文件和go.work.sum
到 git 上, 因为它主要用于本地代码开发,属于临时配置
go.work文件
go.work
文件示例(Go Modules 参考 - Go 编程语言 - Go 编程语言):
# 指定工作区的go版本
go 1.18
# 相对路径是相对go.work文件的路径
# 指定哪些go.mod会加入编译,这个指令不会递归
# 假设your-module引用了upstream-mod,那么还相当于自动给your-module添加了replace指令,将upstream-mod重定向到本地path-to-upstream-mod-dir的版本
use (./path-to-upstream-mod-dir./path-to-your-module
)replace (golang.org/x/net v1.2.3 => ./fork/netgolang.org/x/net => ./fork/net
)
注意:
go.work
文件中的定义优先于go.mod
的定义,比如同时在go.work
和go.mod
中 replace 分别指定不同的代码仓库路径,实际采用的是go.work
中的。
常用命令
-
go env GOWORK
查看当前工作区根路径(就是go.work
的绝对路径) -
go run/build 工作区被use的目录
编译工作区中的指定模块 -
go work init
初始化工作区文件, 用于生成go.work
工作区文件# hello目录必须存在,且其下必须存在go.mod文件 go work init ./hello
-
go work use
添加go模块到工作区# 添加一个模块到工作区 go work use ./example # 添加多个模块到工作区 go work use ./example ./example1 # 递归查找-r后面的路径参数下的所有子目录,把所有包含go.mod文件的子目录都添加到go work文件中 go work use -r ./example
-
go work edit
用于编辑go.work
文件。手动编辑该文件也可以,这个命令是方便给命令行工具使用。# 重新格式化 go.work 文件 go work edit -fmt go.work # 替换代码模块 go work edit -replace=github.com/link1st/example=./example go.work # 删除替换代码模块 go work edit -dropreplace=github.com/link1st/example # 添加新的模块到工作区 go work edit -use=./example go.work # 从工作区中删除模块 go work edit -dropuse=./example go.work # 查看工作区信息 go work edit -json # 查看工作区模块列表 go work use
-
go work sync
把go.work
文件里的依赖同步到workspace包含的各Module的go.mod
文件中。比如go.work中use了app模块和utils模块。现在 app 模块依赖了 utils 模块的v1.0.0版本。现在 utils 远端升级到了 v1.1.0 版本,因此我们在 app/go.mod 中添加了require example.com/utils v1.1.0
指令。同时本地的 utils 包应该手动拉取更新(因为go.work中use了会让go编译时使用本地的版本)或者用go work sync
来检查依赖的 utils 是不是期望的v1.1.0
版本。