# 本地同时改几个互相依赖的 Go 模块，还不想把 replace 写进各自的 go.mod

**URL:** <https://www.shiqidu.com/t/topic/2051>\
**Category:** 开发调优\
**Tags:** 问与答, Linux, Go, 编程, 开源软件\
**Created:** [2026 年11 月 12 日 13:24 UTC](https://www.shiqidu.com/t/topic/2051 "2026-11-12T13:24:25Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

作者： ![shiqidu\_editor](https://www.shiqidu.com/user_avatar/www.shiqidu.com/shiqidu_editor/32/528_2.png) [@shiqidu\_editor](https://www.shiqidu.com/u/shiqidu_editor)\
发布日期： [2026 年11 月 12 日 13:24 UTC](https://www.shiqidu.com/t/topic/2051/1 "2026-11-12T13:24:25Z")

</div>

只在自己机器上改一个依赖模块，马上要在另一个模块里验证，这种来回很常见。若把 `replace` 写进各自的 `go.mod`，同事拉下来的构建也会跟着变。

官方的 [多模块工作区教程](https://go.dev/doc/tutorial/workspaces) 给出的做法是：在多个模块的共同上级目录里执行 `go work init`，把要一起参与构建的模块路径写进新生成的 `go.work`。之后再用 `go work use` 追加目录。教程里的示例文件包含一行 `go` 指令和若干 `use` 指令，语法和 `go.mod` 相近。加入工作区之后，Go 命令会把这些模块都当作主模块来解析，因此可以在一个模块里改代码，立刻被同一工作区里的另一个模块用到，而不必先把 `replace` 写进各模块自己的 `go.mod`。教程也写明，工作区可以用来代替在模块之间添加 `replace` 指令，方便同时修改。`go work use` 还可以带 `-r`，递归检查子目录并把其中的模块一并写进去。

工作区并不会取代模块本身。每个模块仍然要有自己的 `go.mod`，发布时还是按模块打版本。教程的后续步骤是给被依赖的模块做一次正式发布，再在依赖方用 `go get` 打到具体版本，这样在工作区之外也能正确解析。[模块参考里关于工作区的部分](https://go.dev/ref/mod#go-work-file) 把工作区定义为一组磁盘上的模块，在最小版本选择时作为主模块集合使用。没有 `go.work` 时，工作区就只包含当前目录所属的那一个模块。`use` 指令的参数是模块根目录（里面有 `go.mod`）的相对路径，不加 `-r` 时不会自动把子目录里的其他模块加进来，那些目录需要各自写一条 `use`。参考还提到，`go.work` 里也可以写 `replace`，并且会覆盖工作区模块 `go.mod` 里对同一模块的替换。若多个主模块之间的 `replace` 互相冲突，必须在 `go.work` 里删掉或改写清楚。多数与模块相关的子命令会按当前工作区来运作，但 `go mod tidy`、`go get`、`go mod vendor` 这类命令始终只作用于单个主模块，不会因为开了工作区就把几个模块的依赖表一次性收拾完。

要不要把 `go.work` 提交进版本库，参考的态度偏谨慎：签入的文件可能盖住开发者在父目录里自己的工作区，也可能让持续集成选到错误的依赖版本并测错行为。该页同时承认，若仓库里这组模块只在彼此之间共同开发、几乎不会和外部模块拼出另一套组合，提交一份 `go.work` 可以说得通，但各个模块仍应被单独测试和发布。不确定当前启用的是哪一份工作区文件时，可以用 `go env GOWORK` 查看。临时关掉则把 `GOWORK` 设成 `off`，也可以让它指向另一个以 `.work` 结尾的文件。命令方面，除了 `init` 和 `use`，还有 `go work edit` 做低级编辑，以及 `go work sync` 把工作区构建列表里的依赖同步回各模块。工作区还会维护一份 `go.work.sum`，用来记录各模块自己的 `go.sum` 里尚未收录、但工作区用到的校验和。

这和在 `go.mod` 里用 `ignore` 指令排除目录、调整 `vet` 范围不是同一件事，后者可以看站内这篇 [Go 1.25 与 go.mod ignore](https://www.shiqidu.com/t/topic/1915)。工作区也不是 Git 的 worktree：工作区管的是一次构建里同时启用哪些本地模块，不是同一仓库的多份工作副本。

你现在是几个服务模块要一起改，还是一个主模块加这份主模块所依赖的本地库？

---

<div class="post-metadata">

作者： ![Leon](https://www.shiqidu.com/user_avatar/www.shiqidu.com/leon/32/5_2.png) [@Leon](https://www.shiqidu.com/u/Leon)\
发布日期： [2026 年11 月 12 日 16:28 UTC](https://www.shiqidu.com/t/topic/2051/5 "2026-11-12T16:28:46Z")

</div>

go.work 我用了大半年，栽过两次。

第一次是把文件提交进库了。同事那边本地多 clone 了一份模块，go work use 一跑路径全变了，构建直接挂，排查了半天以为是依赖出问题。

第二次是 go.work.sum。它单独维护一份，还经常跟各模块自己的 go.sum 对不上，报 checksum mismatch。后来我干脆不提交了，让它本地生成，成本是第一次跑要联网拉一遍。

CI 那边完全不认 go.work，显式 GOWORK=off 走各模块自己的 go.mod。不然本地能过、CI 挂，那种感觉比直接报错还难受。
