Go1.25 新特性:Go modules 終于要支持 Git 子目錄,太感人了?。?!
大家好,我是煎魚(yú)。
在過(guò)去 Go 最早是使用 GOPATH 的模塊依賴(lài)管理方式,源于 Go 的大單體倉(cāng)庫(kù)的模式。隨后 @rsc 推行了 Go modules(也就是現(xiàn)在的 go.mod)的模塊依賴(lài)管理方式。
但 Go modules 本身也依然有不少的問(wèn)題點(diǎn),其中一個(gè)是類(lèi)似 GitLab subgroups 的兼容適配問(wèn)題。
與我們今天分享的問(wèn)題點(diǎn)也比較相近。
業(yè)務(wù)背景
原提案作者 @Anmol Sethi 有一個(gè)開(kāi)源項(xiàng)目 nhooyr/websocket[1]
圖片
該項(xiàng)目的倉(cāng)庫(kù)根目錄塞滿(mǎn)了 Go 文件,造成頁(yè)面混亂、不容易閱讀。(作者自述)
于是作者想要將模塊源碼遷移到倉(cāng)庫(kù)下的子模塊,這樣可以實(shí)現(xiàn)根目錄就干凈了,文檔和配置文件也不會(huì)和源碼混在一起,更利于維護(hù)與閱讀。
但是很無(wú)奈的是,Go 并不支持模塊在倉(cāng)庫(kù)子目錄中的情況,導(dǎo)致如果嘗試:
go get github.com/nhooyr/websocket/mod@latest或在 go.mod 中這樣引用:
require github.com/nhooyr/websocket/mod v0.1.0就會(huì)失敗,因?yàn)?go module 無(wú)法識(shí)別子模塊的場(chǎng)景。這是該作者遇到的真實(shí)案例。
不支持的原因
在 Go 的模塊代理機(jī)制中,cmd/go 會(huì)根據(jù)代碼里對(duì)應(yīng)的 go-import meta 標(biāo)簽來(lái)定位模塊的位置。
例如下面這個(gè)最常見(jiàn)的 group/project 例子,我們模仿 go get 命令直接拉?。?/span>
curl -X GET "https://gitlab.xxx.com/libraries/example?go-get=1"
<html><head><meta name="go-import" cnotallow="gitlab.xxx.com/libraries/example git https://gitlab.xxx.com/libraries/example.git" /></head></html>現(xiàn)有的 cmd/go 機(jī)制只會(huì)把倉(cāng)庫(kù)根目錄當(dāng)作模塊根。
如果在 Git 倉(cāng)庫(kù)中,實(shí)際把 go 模塊源碼放在子目錄(例如:github.com/eddycjy/repo/subdir),則 cmd/go 無(wú)法正確處理。
Go1.25 新特性:Go 模塊將支持 Git 子目錄
@Anmol Sethi 發(fā)起了新提案《cmd/go: allow serving module under the subdirectory of git repository[2]》:
圖片
期望去推動(dòng)并解決這個(gè)問(wèn)題。
最終定論是,允許在 go-import meta 標(biāo)簽中明確支持指定子目錄,例如:
<meta name="go-import" cnotallow="example.com/repo git https://.../repo sub/dir">這樣 Go 命令就可以把模塊定位在包含源碼的子目錄中,而不是整個(gè)倉(cāng)庫(kù)根目錄。
核心變更上主要是對(duì) cmd/go 的解析邏輯進(jìn)行了擴(kuò)展,支持新 meta 標(biāo)簽格式 root-path vcs repo-url subdir 的解析:
圖片
以此達(dá)到了 go-import 元標(biāo)記中指定子目錄的功能。
對(duì) Go 官方這部分具體代碼感興趣的同學(xué),可以查看以下 CL《cmd/go: add subdirectory support to go-import meta tag[3]》:
圖片
總結(jié)
這個(gè)提案目前已經(jīng)通過(guò)并且合并,預(yù)計(jì)將會(huì)在 Go1.25 中開(kāi)始正式應(yīng)用。也是廣大 Go 開(kāi)發(fā)者的好消息了。

而且普遍從 issues 來(lái)看,大家都認(rèn)為這將是一個(gè)比較實(shí)用的改進(jìn),特別適合 monorepo 維護(hù)與多語(yǔ)言項(xiàng)目結(jié)構(gòu)。
參考資料
[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

































