Go1.18 快訊:這個(gè)新特性太實(shí)用了
閱讀本文大概需要 5 分鐘。
大家好,我是 polarisxu。
工作區(qū)模式(Workspace mode),可不是之前 GOPATH 時(shí)代的 Workspace,而是希望在本地開發(fā)時(shí)支持多 Module。
01 緣起
為了大家全面理解工作區(qū)模式,通過一個(gè)具體例子講解。
本地有兩個(gè)項(xiàng)目,分別是兩個(gè) 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 中增加如下內(nèi)容:
package?main
import?(
????"github.com/polaris1119/mypkg"
)
func?main()?{
????mypkg.Bar()
}
這時(shí)候,如果我們運(yùn)行 go mod tidy,肯定會(huì)報(bào)錯(cuò),因?yàn)槲覀兊?mypkg 包根本沒有提交到 github 上,肯定找不到。
fatal:?repository?'https://github.com/polaris1119/mypkg/'?not?found
go run main.go 也就不成功。
我們當(dāng)然可以提交?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
再次運(yùn)行 go run main.go,輸出如下:
$?go?run?main.go
This?is?package?mypkg
當(dāng)都開發(fā)完成時(shí),我們需要手動(dòng)刪除 replace,并執(zhí)行 go mod tidy 后提交,否則別人使用就報(bào)錯(cuò)了。
這還是挺不方便的,如果本地有多個(gè) module,每一個(gè)都得這么處理。
02 工作區(qū)模式
針對上面的這個(gè)問題,Michael Matloob 提出了 Workspace Mode(工作區(qū)模式)。相關(guān) issue 討論:cmd/go: add a workspace mode[1],這里是 Proposal[2]。
為了能夠試驗(yàn)工作區(qū),請?jiān)诒镜厥褂?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????|???*????|
我本地當(dāng)前 tip 版本:
$?go?version
go?version?devel?go1.18-c78a267bd4?Sat?Nov?13?01:39:23?2021?+0000?darwin/amd64
通過 go help work 可以看到 work 相關(guān)命令:
Go?workspace?provides?access?to?operations?on?worskpaces.
Note?that?support?for?workspaces?is?built?into?many?other?commands,
not?just?'go?work'.
See?'go?help?modules'?for?information?about?Go's?module?system?of
which?workspaces?are?a?part.
Usage:
?go?work??[arguments]
The?commands?are:
?edit????????edit?go.work?from?tools?or?scripts
?init????????initialize?workspace?file
?sync????????sync?workspace?build?list?to?modules
?use?????????add?modules?to?workspace?file
Use?"go?help?work?"?for?more?information?about?a?command.
根據(jù)這個(gè)提示,我們初始化 workspace:
$?cd?~/polarisxu
$?go?work?init?mypkg?example
$?tree
.
├──?example
│???├──?go.mod
│???└──?main.go
├──?go.work
└──?mypkg
????├──?bar.go
????└──?go.mod
注意幾點(diǎn):
多個(gè)子模塊應(yīng)該在一個(gè)目錄下。比如這里的 polarisxu 目錄;(這不是必須的,但更好管理,否則 go work init 需要提供正確的子模塊路徑) go work init 需要在 polarisxu 目錄執(zhí)行; go work init 之后跟上需要本地開發(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 目錄下,這么運(yùn)行:go run example/main.go,也能正常。
注意,go.work 不需要提交到 Git 中,因?yàn)樗皇悄惚镜亻_發(fā)使用的。
如果想要禁用 workspace,可以通過 -workfile=off 實(shí)現(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,這樣運(yùn)行你會(huì)發(fā)現(xiàn)又報(bào)錯(cuò)了。但通過這種方式,你可以驗(yàn)證依賴包提交到 github 上之后的情況。
03 總結(jié)
在 GOPATH 年代,多 GOPATH 是一個(gè)頭疼的問題。當(dāng)時(shí)沒有很好的解決,Module 就出現(xiàn)了,多 GOPATH 問題因此消失。但多 Module 問題隨之出現(xiàn)。Workspace 方案較好的解決了這個(gè)問題。
下篇文章,我會(huì)進(jìn)一步講解,如何在 VSCode 中試驗(yàn) Workspace。
參考資料
cmd/go: add a workspace mode: https://github.com/golang/go/issues/45713
[2]這里是 Proposal: https://go.googlesource.com/proposal/+/master/design/45713-workspace.md
我是 polarisxu,北大碩士畢業(yè),曾在 360 等知名互聯(lián)網(wǎng)公司工作,10多年技術(shù)研發(fā)與架構(gòu)經(jīng)驗(yàn)!2012 年接觸 Go 語言并創(chuàng)建了 Go 語言中文網(wǎng)!著有《Go語言編程之旅》、開源圖書《Go語言標(biāo)準(zhǔn)庫》等。
堅(jiān)持輸出技術(shù)(包括 Go、Rust 等技術(shù))、職場心得和創(chuàng)業(yè)感悟!歡迎關(guān)注「polarisxu」一起成長!也歡迎加我微信好友交流:gopherstudio
