Go1.18 快訊:Module 工作區(qū)模式,太棒了
大家好,我是 polarisxu。
工作區(qū)模式(Workspace mode),可不是之前 GOPATH 時代的 Workspace,而是希望在本地開發(fā)時支持多 Module。
01 緣起
為了大家全面理解工作區(qū)模式,通過一個具體例子講解。
本地有兩個項目,分別是兩個 module:mypkg 和 example。(Windows 系統(tǒng)請按自己方式創(chuàng)建目錄)
$?cd?~/
$?mkdir?polarisxu
$?cd?polarisxu
$?mkdir?mypkg?example
$?cd?mypkg
$?go?mod?init?github.com/polaris1119/mypkg
$?touch?bar.go
在 bar.go 中增加如下示例代碼:
package?mypkg
func?Bar()?{
?println("This?is?package?mypkg")
}
接著,在 example 模塊中處理:
$?cd?~/polarisxu/example
$?go?mod?init?github.com/polaris1119/example
$?touch?main.go
在 main.go 中增加如下內容:
package?main
import?(
????"github.com/polaris1119/mypkg"
)
func?main()?{
????mypkg.Bar()
}
這時候,如果我們運行 go mod tidy,肯定會報錯,因為我們的 mypkg 包根本沒有提交到 github 上,肯定找不到。
fatal:?repository?'https://github.com/polaris1119/mypkg/'?not?found
go run main.go 也就不成功。
我們當然可以提交 mypkg 到 github,但我們沒修改一次 mypkg,就需要提交,否則 example 中就沒法使用上最新的。
針對這種情況,目前是建議通過 replace 來解決,即在 example 中的 go.mod 增加如下 replace:(v1.0.0 根據(jù)具體情況修改,還未提交,可以使用 v1.0.0)
module?github.com/polaris1119/example
go?1.17
require?github.com/polaris1119/mypkg?v1.0.0
replace?github.com/polaris1119/mypkg?=>?../mypkg
再次運行 go run main.go,輸出如下:
$?go?run?main.go
This?is?package?mypkg
當都開發(fā)完成時,我們需要手動刪除 replace,并執(zhí)行 go mod tidy 后提交,否則別人使用就報錯了。
這還是挺不方便的,如果本地有多個 module,每一個都得這么處理。
02 工作區(qū)模式
針對上面的這個問題,Michael Matloob 提出了 Workspace Mode(工作區(qū)模式)。相關 issue 討論:[cmd/go: add a workspace mode](cmd/go: add a workspace mode "cmd/go: add a workspace mode"),這里是 Proposal[1]。
為了能夠試驗工作區(qū),請在本地使用 gotip,建議通過 goup 切換 Go 版本:
$?goup?install?tip
$?goup?show
|??VERSION??|?ACTIVE?|
|-----------|--------|
|???1.0.1???|????????|
|????1.1????|????????|
|??1.10.8???|????????|
|??1.14.9???|????????|
|??1.15.2???|????????|
|??1.15.3???|????????|
|??1.15.4???|????????|
|???1.16????|????????|
|??1.16.2???|????????|
|?1.16beta1?|????????|
|???1.17????|????????|
|?1.17beta1?|????????|
|????1.4????|????????|
|???1.4.3???|????????|
|????tip????|???*????|
我本地當前 tip 版本:
$?go?version
go?version?devel?go1.18-a4b2c579e9?Wed?Nov?3?00:49:50?2021?+0000?darwin/amd64
通過 go help mod 可以看到,新增了 work 相關的兩個子命令:
The?commands?are:
??...
?editwork????edit?go.work?from?tools?or?scripts
?...
?initwork????initialize?workspace?file
?...
根據(jù)這個提示,我們初始化 workspace:
$?cd?~/polarisxu
$?go?mod?initwork?mypkg?example
$?tree
.
├──?example
│???├──?go.mod
│???└──?main.go
├──?go.work
└──?mypkg
????├──?bar.go
????└──?go.mod
注意幾點:
多個子模塊應該在一個目錄下。比如這里的 polarisxu 目錄;(這不是必須的,但更好管理,否則 go mod initwork 需要提供正確的子模塊路徑) go mod initwork 需要在 polarisxu 目錄執(zhí)行; go mod initwork 之后跟上需要本地開發(fā)的子模塊目錄名;
打開 go.work 看看長什么樣:
go?1.18
directory?(
????./example
????./mypkg
)
go.work 文件的語法和 go.mod 類似,因此也支持 replace。
現(xiàn)在,我們將 example/go.mod 中的 replace 語句刪除,再次執(zhí)行 go run main.go(在 example 目錄下),得到了正常的輸出。也可以在 polarisxu 目錄下,這么運行:go run example/main.go,也能正常。
注意,go.work 不需要提交到 Git 中,因為它只是你本地開發(fā)使用的。
如果想要禁用 workspace,可以通過 -workfile=off 實現(xiàn)。
-workfile?file
??in?module?aware?mode,?use?the?given?go.work?file?as?a?workspace?file.
??By?default?or?when?-workfile?is?"auto",?the?go?command?searches?for?a
??file?named?go.work?in?the?current?directory?and?then?containing?directories
??until?one?is?found.?If?a?valid?go.work?file?is?found,?the?modules
??specified?will?collectively?be?used?as?the?main?modules.?If?-workfile
??is?"off",?or?a?go.work?file?is?not?found?in?"auto"?mode,?workspace
??mode?is?disabled.
比如:go run -workfile=off main.go 或 go build -workfile=off,這樣運行你會發(fā)現(xiàn)又報錯了。但通過這種方式,你可以驗證依賴包提交到 github 上之后的情況。
03 總結
在 GOPATH 年代,多 GOPATH 是一個頭疼的問題。當時沒有很好的解決,Module 就出現(xiàn)了,多 GOPATH 問題因此消失。但多 Module 問題隨之出現(xiàn)。Workspace 方案較好的解決了這個問題。
下篇文章,我會進一步講解,如何在 VSCode 中試驗 Workspace。
參考資料
這里是 Proposal: https://go.googlesource.com/proposal/+/master/design/45713-workspace.md
推薦閱讀
