go.work必须放在工作区根目录,且该目录不等于任一模块根目录;它需能俯视所有模块,如auth、payment、shared,应新建myproject文件夹统一存放并在此执行go work init。

go.work 文件该放在哪一级目录
必须放在工作区根目录,且这个目录不等于任意一个模块的根目录。它要能“俯视”所有待管理的模块,比如你有 auth、payment、shared 三个独立模块,就新建一个空文件夹叫 myproject,把它们全放进去,再在 myproject 下执行 go work init。
常见错误现象:go run main.go 报 no required module provides package ...,往往是因为 go.work 放在了某个模块内部(比如 auth/go.work),导致 Go 只看到那个模块,看不到其他。
- 工作区根目录 ≠
go.mod所在目录 —— 它们可以完全不重叠 - 运行
go work use ./auth ./payment时,路径必须是相对于go.work当前位置的相对路径 - 如果模块路径含空格或特殊字符,
go.work会静默失败,建议全用小写字母+短横线
go.work 中 replace 和 use 的区别和顺序影响
use 告诉 Go “这些模块我打算一起开发”,replace 是“把这个模块的依赖临时指向本地路径”。两者共存时,replace 优先级更高,但只对被 use 的模块生效 —— 换句话说,没 use 的模块,连 replace 都不会被加载。
典型场景:你在改 shared 库,同时想让 auth 和 payment 都用上最新版,而不是 go.sum 里锁死的老版本。
use列表必须显式包含所有参与开发的模块,漏一个就会走远程拉取逻辑replace写成github.com/myorg/shared => ./shared,注意箭头两边不能有空格- 如果
shared本身又依赖github.com/some/dep,而你想也替换成本地版,得额外加一条replace,use不会递归生效
vscode + gopls 对 go.work 的识别问题
gopls 默认只读取当前打开文件夹下的 go.work,如果你在 vscode 里直接打开的是 auth 子目录,哪怕父目录有 go.work,它也看不到其他模块,补全和跳转会断。
解决方法很简单:关掉当前窗口,用 vscode 打开整个工作区根目录(即 go.work 所在目录)。
- vscode 状态栏右下角显示
Go (workspace)才算正常;如果显示Go (module: auth)就说明没加载 workspace - 修改
go.work后,需手动触发Developer: Restart Language Server,否则 gopls 缓存不刷新 - 如果项目里混用了
replace和gomodfile插件,可能冲突,建议禁用后者
CI/CD 中要不要提交 go.work?怎么处理本地路径
要提交,但内容必须不含开发者本地路径。CI 环境无法解析 ./auth 这种相对路径,除非你保证所有模块都以固定结构检出(比如统一放在 $HOME/src/ 下)。
更稳妥的做法是:CI 中不用 go.work,改用 go mod edit -replace 动态打补丁,或者干脆用 go get -u ./... 强制更新依赖。
- 提交前检查
go.work里所有use行是否都是干净的相对路径(如./auth),绝不能出现/Users/xxx/myproject/auth - CI 脚本中避免
go work use,它会修改文件,污染 git 状态 - 本地开发用
go.work提效,CI 用传统go mod流程更可控 —— 二者不必强求一致