问题背景
Golang 在1.18 推出了新特性 workspace 工作区模式
- 为什么要有 workspace
- 什么是 workspace
- 怎么使用 workspace
在工作过程中发现,模块的go.mod中添加了很多 replace
,其实是为了解决依赖的问题。例如有2个module
处于开发阶段,一个是example.com/web
,一个是example.com/util
。example.com/web
依赖example.com/util
的函数,当两个模块同时开发过程中,为了 web
模块能够时候用到最新的 util
模块代码,有两种方案
方案1:就是将模块及时提交代码到代码仓库
- 如果
util
有修改,那么就需要将代码提交到代码仓库,然后打上 tag - 然后使用 go get -u 更新 main 中依赖的 util 的版本号(tag)
缺点:每次需要提交代码并更新到最新
方案2:使用go.mod中使用replace
指令,见代码
目录结构:
1 | module |
文件web/web.go
:
1 | package main |
文件web/go.mod
:
1 | module example.com/web |
文件util/util.go
:
1 | package util |
文件util/go.mod
1 | module example.com/util |
通过replace
指令,使用go命令编译代码的时候,会找到本地的util目录,这样example.com/web
就可以使用到本地最新的example.com/util
代码
缺点:提交
example.com/web
这个module的代码到代码仓库时,需要删除最后的replace指令,否则其他开发者下载后会编译报错,因为他们本地可能没有util目录,或者util目录的路径和你的不一样
工作区
为了解决方案2的痛点,Go1.18 新增了工作区模式(workspace mode)
去掉 web/go.mod
中的 replace
命令
1 | module example.com/web |
在 web 模块中执行 go run hello.go
,提示找不到依赖模块
1 | hello.go:6:2: missing go.sum entry for module providing package example.com/util; to add: |
使用 go work init web util
指定工作模块 web
与 util
,会生成 go.work
文件
1 | go 1.18 |
其中 use
用于表示需要指定的模块,再次执行 go run hello.go
,则运行成功
目录结构
1 | module |
命令
1 | root@13ce5bc74ac3:/code/module-workspace# go help work |
-
通常情况下,建议不要提交 go.work 文件到 git上,因为它主要用于本地代码开发
-
推荐在
$GOPATH
路径下执行,生成 go.work 文件 -
go work init
初始化工作区文件,用于生成go.work工作区文件 -
go work use
添加新的模块到工作区间1
2
3go work use ./example 添加一个模块到工作区
go work use ./example ./example1 添加多个模块到工作区
go work use -r ./example 递归 ./example 目录到当前工作区 -
go work edit
用于编辑 go.work文件1
2
3
4
5
6//可以使用 edit 命令编辑和手动编辑 go.work 文件效果是相同的 示例:
go work edit -fmt go.work 重新格式化 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 sync
将工作区的构建列表同步到工作区的模块 -
go env GOWORK
查看环境变量,查看当前工作区文件路径 可以排查工作区文件是否设置正确,go.work 路径找不到可以使用GOWORK
指定,生成多个go.work
则指向最后一次生成的路径 -
replace
指令的语法与 go.mod 中的replace
指令相同,并优先于 go.mod 文件中的替换。这是主要用于覆盖不同工作区中的冲突替换模块