Go1.16 新特性:Go mod 的后悔藥,僅需這一招
本文轉(zhuǎn)載自微信公眾號(hào)「腦子進(jìn)煎魚(yú)了」,作者陳煎魚(yú) 。轉(zhuǎn)載本文請(qǐng)聯(lián)系腦子進(jìn)煎魚(yú)了公眾號(hào)。
大家好,我是正在學(xué)習(xí)煎魚(yú)的煎魚(yú)。
前幾天 Go 官方正式發(fā)布了 1.16 版本。從這個(gè)版本起,環(huán)境變量 GO111MODULE 的默認(rèn)值正式修改為 on。
這也意味著 Go modules 將更進(jìn)一步推進(jìn)其業(yè)務(wù)覆蓋面,有新老項(xiàng)目共存的小伙伴建議手動(dòng)將 GO111MODULE 調(diào)整為 auto。
Go1.16 針對(duì) Go modules 放出了一個(gè)新特性,能夠讓維護(hù)第三方庫(kù)(需含 Go mod)的開(kāi)發(fā)者擁有反復(fù)吃 “后悔藥” 的權(quán)力,可以提醒使用者已發(fā)布的 “臟” 版本存在問(wèn)題及了解其原因。
這個(gè)新特性,對(duì)于許多維護(hù)和使用公共庫(kù)(開(kāi)源、企業(yè)等)的小伙伴簡(jiǎn)直是一個(gè)小福音,建議大家都應(yīng)該要了解這個(gè)知識(shí)點(diǎn)。
在接下來(lái)文章中將進(jìn)行詳細(xì)說(shuō)明和介紹。
后悔藥:Go mod retract
Go1.16 起可以在 go.mod 文件中使用 retract 指令來(lái)聲明該第三方模塊的某些發(fā)行版本不能被其他模塊使用。
在使用場(chǎng)景上:在發(fā)現(xiàn)嚴(yán)重問(wèn)題或無(wú)意發(fā)布某些版本后,模塊的維護(hù)作者可以撤回該版本,支持撤回單個(gè)或多個(gè)版本。
以前沒(méi)有辦法解決,因此一旦出現(xiàn)就非常麻煩。對(duì)應(yīng)兩者的操作如下:
- 維護(hù)者:
- 刪除有問(wèn)題版本的 tag。
- 重新打一個(gè)新版本的 tag。
- 使用者:
- 發(fā)現(xiàn)有問(wèn)題的版本 tag 丟失,需手動(dòng)介入。
- 不知道有問(wèn)題,由于其他庫(kù)依賴(lài),因此被動(dòng)升級(jí)而踩坑。
因此在本次 Go1.16 發(fā)布后,就擁有了一個(gè)半止損的新手段了,也可以作為 Go mod 自動(dòng)更新的大坑的補(bǔ)全辦法之一。
實(shí)戰(zhàn)演練
為了方便演示,首先創(chuàng)建一個(gè) Demo 項(xiàng)目(github.com/eddycjy/go-retract-demo),其含有一個(gè)基礎(chǔ)方法:
- package go_retract_demo
- func HelloWorld() string {
- return "001:腦子進(jìn)煎魚(yú)了!"
- }
另外有一個(gè)應(yīng)用工程依賴(lài)了該第三方庫(kù),代碼如下:
- func main() {
- // import demo "github.com/eddycjy/go-retract-demo"
- s := demo.HelloWorld()
- fmt.Println(s)
- }
對(duì)應(yīng)的 go.mod 文件如下:
- module github.com/eddycjy/awesomeProject
- go 1.16
- require github.com/eddycjy/go-retract-demo v0.0.1
retract 特性演示
但隨著時(shí)間不斷推移,第三方開(kāi)源庫(kù) eddycjy/go-retract-demo 即將迭代到 v0.3.0 時(shí),發(fā)現(xiàn)以往的 v0.2.0 是有 BUG 的。
需要緊急的在v0.3.0 版本把這個(gè) BUG 修復(fù)并提醒出去。此時(shí)可以在 go.mod 文件中寫(xiě)入 retract 指令:
- module github.com/eddycjy/go-retract-demo
- go 1.16
- // 因?yàn)榧弭~(yú)不小心敲錯(cuò)了...
- retract v0.2.0
指令上面為撤回的原因,后面是具體的版本。如果涉及多版本,可以如下編寫(xiě):
- retract (
- v0.1.0
- v0.2.0
- )
retract 特性效果
成功發(fā)布最新版本 v0.3.0 版本并指定 retract 后。所有引用了該庫(kù)的工程應(yīng)用,執(zhí)行 go list 就可以看到如下提醒:
- $ go1.16 list -m -u all
- xxx/eddycjy/awesomeProject
- xxx/eddycjy/go-retract-demo v0.2.0 (retracted) [v0.3.0]
結(jié)合該命令,我們?nèi)粘J褂玫?IDE(例如:GoLand),其在保存時(shí)是會(huì)默認(rèn)執(zhí)行 go list 命令的。在后續(xù) IDE 支持后,就可以在編碼時(shí)就快速發(fā)現(xiàn)有問(wèn)題的版本和提示。
在手動(dòng)執(zhí)行 go get 時(shí)也會(huì)出現(xiàn) warning 提示,會(huì)把 go.mod 文件上的原因注釋顯示出來(lái):
- $ go1.16 get github.com/eddycjy/go-retract-demo@v0.2.0
- go: warning: github.com/eddycjy/go-retract-demo@v0.2.0: retracted by module author: 因?yàn)榧弭~(yú)不小心敲錯(cuò)了...
- go: to switch to the latest unretracted version, run:
- go get github.com/eddycjy/go-retract-demo@latest
這樣就能看到是哪個(gè)模塊依賴(lài),因?yàn)槭裁丛蛞蟪坊亓?,非常直觀。
總結(jié)
以往在出問(wèn)題后每個(gè)個(gè)體需要跑去問(wèn)維護(hù)者或者看 GitHub Commits,那樣總歸非常麻煩,很可能一來(lái)一回半個(gè)鐘就沒(méi)了。
新特性給予了 Go modules 軟撤回版本的一個(gè)方法,能夠把問(wèn)題更直觀的反饋到開(kāi)發(fā)者的手中,再結(jié)合日常開(kāi)發(fā)工具的話(huà)更是美哉。
但這個(gè)特性的完全應(yīng)用目前也是有一定的阻礙的:
- 國(guó)內(nèi)模塊代理:需要國(guó)內(nèi)的模塊代理也支持 retract ,否則即使你更新了版本也沒(méi)有提示處理。
- IDE:IDE 針對(duì) retract 做一些支持,例如:文字顏色標(biāo)紅、黃等,能夠便于開(kāi)發(fā)者更好的識(shí)別。
你對(duì) Go modules 的 retract 特性怎么看,歡迎一起留言討論!