点击关注后,你不仅获得一个找资源的工具,更获得一个有趣的灵魂 ▶ ▶ ▶
在过去 Go 最早是使用 GOPATH 的模块依赖管理方式,源于 Go 的大单体仓库的模式。随后 @rsc 推行了 Go modules(也就是现在的 go.mod)的模块依赖管理方式。
但 Go modules 本身也依然有不少的问题点,其中一个是类似 GitLab subgroups 的兼容适配问题。
与我们今天分享的问题点也比较相近。
业务背景
原提案作者 @Anmol Sethi 有一个开源项目 nhooyr/websocket[1]

该项目的仓库根目录塞满了 Go 文件,造成页面混乱、不容易阅读。(作者自述)
于是作者想要将模块源码迁移到仓库下的子模块,这样可以实现根目录就干净了,文档和配置文件也不会和源码混在一起,更利于维护与阅读。
但是很无奈的是,Go 并不支持模块在仓库子目录中的情况,导致如果尝试:
go get github.com/nhooyr/websocket/mod@latest
或在 go.mod 中这样引用:
require github.com/nhooyr/websocket/mod v0.1.0
就会失败,因为 go module 无法识别子模块的场景。这是该作者遇到的真实案例。
不支持的原因
在 Go 的模块代理机制中,cmd/go
会根据代码里对应的 go-import meta
标签来定位模块的位置。
例如下面这个最常见的 group/project 例子,我们模仿 go get 命令直接拉取:
curl -X GET "https://gitlab.xxx.com/libraries/example?go-get=1"
"go-import" content="gitlab.xxx.com/libraries/example git https://gitlab.xxx.com/libraries/example.git" />
现有的
cmd/go
机制只会把仓库根目录当作模块根。
如果在 Git 仓库中,实际把 go 模块源码放在子目录(例如:github.com/eddycjy/repo/subdir
),则 cmd/go
无法正确处理。
Go1.25 新特性:Go 模块将支持 Git 子目录
@Anmol Sethi 发起了新提案《cmd/go: allow serving module under the subdirectory of git repository[2]》:

期望去推动并解决这个问题。
最终定论是,允许在 go-import meta
标签中明确支持指定子目录,例如:
"go-import" content="example.com/repo git https://.../repo sub/dir">
这样 Go 命令就可以把模块定位在包含源码的子目录中,而不是整个仓库根目录。
核心变更上主要是对 cmd/go
的解析逻辑进行了扩展,支持新 meta 标签格式
root-path vcs repo-url subdir
的解析:

以此达到了 go-import
元标记中指定子目录的功能。
对 Go 官方这部分具体代码感兴趣的同学,可以查看以下 CL《cmd/go: add subdirectory support to go-import meta tag[3]》:

总结
这个提案目前已经通过并且合并,预计将会在 Go1.25 中开始正式应用。也是广大 Go 开发者的好消息了。

而且普遍从 issues 来看,大家都认为这将是一个比较实用的改进,特别适合 monorepo 维护与多语言项目结构。
[1] nhooyr/websocket: https://github.com/coder/websocket
[2] cmd/go: allow serving module under the subdirectory of git repository: https://github.com/golang/go/issues/34055
[3] cmd/go: add subdirectory support to go-import meta tag: https://github.com/benjivesterby/go/commit/835e36fc7f631f74233edfd4ab43b6b56833db86