go work 是 Go 1.18 引入的多模块工作区管理机制,必须用于同一仓库中多个独立 go.mod 模块(如 api/、core/、cli/)需相互引用、统一构建或调试的场景,否则会因“module not in main module”报错。

go work 是什么,什么时候必须用它
当你在同一个代码仓库里维护多个 go.mod 模块(比如 api/、core/、cli/ 各自独立定义依赖),又想让它们彼此引用、统一构建或调试时,go work 就不是可选项,而是必需品。否则 go build 或 go test 会报错:cannot load xxx: module xxx is not in the main module。
它本质是顶层工作区(workspace)的描述文件 go.work,用来显式声明哪些子目录是 Go 模块,并让 go 命令把它们“拼”成一个逻辑整体。
初始化和维护 go.work 文件的正确姿势
别手动写 go.work —— 它结构简单但格式敏感,出错会导致整个 workspace 失效。始终用命令生成和更新:
- 首次创建:
go work init ./api ./core ./cli
- 新增模块目录:
go work use ./admin
- 移除某个模块:
go work use -r ./legacy
- 查看当前生效的模块列表:
go work list
go.work 里不能写相对路径以外的路径(比如不能含 ../),也不能指向空目录或不含 go.mod 的目录;否则 go 命令会静默忽略该条目,但后续 go run 可能找不到包。
立即学习“go语言免费学习笔记(深入)”;
多模块下 import 路径怎么写才不踩坑
模块间 import 不再依赖 GOPATH 或目录深度,只认 module 声明的路径。例如:
-
api/go.mod里写的是module github.com/you/project/api -
core/go.mod里写的是module github.com/you/project/core - 那么在
api/main.go中要导入 core,必须写:import "github.com/you/project/core"
,而不是"../core"或"core"
这个路径必须和目标模块的 go.mod 第一行完全一致,包括大小写和斜杠结尾(不能多也不能少)。IDE(如 VS Code + gopls)通常能自动补全,但 CI 构建失败时,90% 是因为 import 路径和 go.mod 声明不匹配。
go.work 在 CI/CD 和发布时要不要提交
要提交,且必须进版本库。它不是开发环境临时文件,而是项目多模块拓扑的“源代码级声明”。CI 流水线(比如 GitHub Actions)需要它才能正确解析模块关系、执行 go test ./... 或 go build ./cmd/...。
但注意两点:
-
go.work中的路径是相对于它自身位置的,所以它应该放在仓库根目录,且所有use路径都用./xxx形式 - 不要在
go.work里用replace或exclude—— 这些属于单模块控制逻辑,应写在对应go.mod里;go.work只做模块发现,不干预依赖解析
最容易被忽略的是:本地开发时 go.work 生效,但某些旧版 Go(GOWORK=off。










