還能這樣玩?Go 將會(huì)增強(qiáng) Go1 向前兼容性
大家好,我是煎魚(yú)。新春快樂(lè)呀!
年前我們?cè)凇缎研寻?,未?lái)不會(huì)有 Go2 了!》文章中討論了 Go2 的未來(lái),明確了未來(lái)是以 Go1.x.y 為主的 Go1 時(shí)代。
為了實(shí)現(xiàn)這個(gè)北極星目標(biāo),Go 團(tuán)隊(duì)采取的策略分別是:增強(qiáng) Go1 向后兼容(在前文已分享)和 Go1 向前兼容(本文重點(diǎn)內(nèi)容)。
本次要提到的 “向前兼容”,指的是舊版本的 Go 編譯新的 Go 代碼。這個(gè)方向比較少被談?wù)?,甚至特意設(shè)計(jì)。
讓我有種,還能這樣搞的感覺(jué)?
Go1 向前兼容
Go 團(tuán)隊(duì)的大當(dāng)家 Russ Cox,針對(duì)如下幾個(gè)方面做了新設(shè)計(jì)和調(diào)整,輸出了《Proposal: Extended forwards compatibility in Go[1]》,已經(jīng)得到討論,很大概率落地,把版本號(hào)停留在 Go1.x.y。
將會(huì)涉及的部分重點(diǎn)如下:
- 新增 GOTOOLCHAIN 環(huán)境變量的設(shè)置。
- 改變?cè)诠ぷ髂K(work module)中解釋 go 行的方式,增加了新的工具鏈(toolchain)行以此實(shí)現(xiàn)聲明。此對(duì)應(yīng)的是 go.mod 文件的 go 行和toolchain 行。
- 對(duì) go get 等命令進(jìn)行聯(lián)動(dòng)修改,允許對(duì) GOTOOLCHAIN 和工作模塊的 go 版本進(jìn)行修改。
增強(qiáng)工作模塊的 go.mod 和 toolchain
聲明 Go 版本號(hào)
我們會(huì)在 go module 生成時(shí),在 Go 工程下生成一個(gè) go.mod 文件。其中會(huì)包含一個(gè) go 行,將會(huì)聲明該模塊應(yīng)該應(yīng)用的 go 版本語(yǔ)義是什么版本。
如下圖,聲明的是 go1.13:
go.mod 文件中的 go 版本聲明
在該提案落地后,本地安裝的 Go 工具鏈如果比 go 行所聲明的 go 版本新時(shí),它將會(huì)直接提供所要求的舊語(yǔ)義,而不會(huì)重新下載和調(diào)用一個(gè)舊版本的 Go 工具鏈。
但如果 go 行聲明了一個(gè)較新的 Go 工具鏈,那么本地安裝的 Go 工具鏈就會(huì)下載并運(yùn)行較新的工具鏈來(lái)滿(mǎn)足其需求。
以下是一個(gè)例子。
在例子中,我們正在運(yùn)行的版本是 go1.30。但在模塊中,有一個(gè) go.mod 聲明了 go 版本:
Go1.30 會(huì)下載并調(diào)用 go1.30.1 來(lái)完成命令,因?yàn)槟K中要求的 go 版本比本地安裝的更高。
但如果 go.mod 文件中聲明的是:
Go1.30 將自己提供 go1.20rc1 語(yǔ)義,而不是運(yùn)行 go1.20 rc1 工具鏈。因?yàn)楸镜匕惭b的版本更新,可以通過(guò) GODEBUG 來(lái)滿(mǎn)足舊語(yǔ)義的訴求。
聲明 Go 工具鏈版本號(hào)
可能會(huì)有同學(xué)想要運(yùn)行更新版本的 Go 工具鏈,但 Go 語(yǔ)義上還是使用舊版本。
為了滿(mǎn)足這點(diǎn)訴求,go.mod 文件也會(huì)支持 toolchain 行的設(shè)置,以此來(lái)支持新版本的工具鏈的使用。
如果 go.mod 文件中設(shè)置了 toolchain 行,將指定使用的工具鏈版本,go 行只指定語(yǔ)言語(yǔ)義的 Go 版本。
go.mod 文件如下:
作用是將為這個(gè)模塊選擇 go1.18 的語(yǔ)義,使用 go1.20rc1 的工具鏈來(lái)構(gòu)建應(yīng)用。
增強(qiáng) Go 工具鏈 GOTOOLCHAIN
將會(huì)在 Go 工具鏈新增 GOTOOLCHAIN 環(huán)境變量的設(shè)置和使用可以使用 go env -w 設(shè)置。也可以在 go test 時(shí)做如下調(diào)整:
go build 編譯時(shí)可以:
可能會(huì)有同學(xué)疑惑 GOTOOLCHAIN 的默認(rèn)值哪來(lái),有哪些值?
- 設(shè)置GOTOOLCHAIN=local:使用本地安裝的 Go 工具鏈,不會(huì)下載不同版本的工具鏈。這是現(xiàn)在的的默認(rèn)行為。
- 設(shè)置GOTOOLCHAIN=auto:使用工作模塊的 go.mod 中聲明的 go 版本(當(dāng)它比本地安裝的 Go 工具鏈要新時(shí))。
GOTOOLCHAIN 環(huán)境變量的默認(rèn)值取決于 Go 工具鏈。標(biāo)準(zhǔn) Go 發(fā)行版默認(rèn)為 GOTOOLCHAIN=auto,也就是將控制權(quán)交給 go.mod 文件。這是在實(shí)施這個(gè)提案后 99% 會(huì)看到的默認(rèn)行為。
Go 工具鏈的一攬子?xùn)|西里也比較多,例如:go get 命令,也會(huì)對(duì) go.mod 文件中的 go 版本或 toolchain 行進(jìn)行變更,以配合使用。
總結(jié)
在今天這篇文章中,我們介紹了 Go1 兼容性增強(qiáng)中的 “向前兼容” 部分,其中要點(diǎn)是:加大對(duì) go.mod 文件中的 go 行和 toolchain 行和工具鏈 GOTOOLCHAIN 相關(guān)的應(yīng)用。
核心目的是為了將 go 語(yǔ)法語(yǔ)義和 go 工具鏈的版本聲明公開(kāi)出來(lái),達(dá)到隔離使用。再配合 “向后兼容” 中的 GODEBUG 的使用,讓 Go 語(yǔ)言做兼容性時(shí)有更多更大的使用空間來(lái)實(shí)現(xiàn)機(jī)制上的保障。
這么一來(lái),Go 語(yǔ)言在這一塊會(huì)變得異常復(fù)雜,理解成本也會(huì)變高。希望大家后續(xù)在這塊也不要再踩坑了。