Go GOPATH 模式未來(lái)會(huì)怎么樣,會(huì)消失嗎?
大家好,我是煎魚(yú)。
還記得好多年前,我們才剛剛開(kāi)始學(xué)習(xí)和使用 Go 這一門(mén)編程語(yǔ)言。當(dāng)時(shí)依賴管理還在用 GOPATH 模式,為此大家基于此去開(kāi)發(fā)和管理了很多配套工具和流程。
隨著 Go 模塊管理(Module)的成熟,有在用新的,有在用舊的。GOPATH 的去留成為了一個(gè)折騰的問(wèn)題。
GOPATH 存在的問(wèn)題
現(xiàn)階段 Go 維護(hù)既有的 GOPATH 模式,至少存在兩個(gè)重要問(wèn)題:
- 新特性更不上:在模塊代理、校驗(yàn)和數(shù)據(jù)庫(kù)等安全改進(jìn)方面,舊的 GOPATH 模式已被拋在后面。Go 所有的迭代焦點(diǎn)都集中在模塊管理(go.mod)上。
- 無(wú)法識(shí)別版本:舊的 GOPATH 模式的源代碼布局,沒(méi)有提供識(shí)別當(dāng)前使用的 Go 語(yǔ)音版本的方法。
第一點(diǎn)還能說(shuō)可以用,不跟進(jìn),似乎也沒(méi)什么大問(wèn)題。最煩的是第二點(diǎn),之前在 GOPATH 和 Go Module 并立的年代。經(jīng)常會(huì)遇到這個(gè)痛苦的坑。
這里 Go 程序讀取模塊會(huì)有一些分歧:
- Module 模式的程序,讀取 go.mod 的 go 行,確定版本為 Go 1.16。
- GOPATH 模式的程序,由于無(wú)法得知版本,只能假設(shè) Go 是最新版本。
這意味著,如果有人在 GOPATH 模式下開(kāi)發(fā)了可下載的軟件包,他們可以使用 Go 1.16 之后引入的語(yǔ)言特性,比如泛型。但當(dāng)用戶在 Module 模式下以模塊的形式下載這些代碼時(shí),這些代碼會(huì)被解釋為 Go1.16,無(wú)法編譯。
隨著時(shí)間的推移,其他語(yǔ)言特性或變更的出現(xiàn),這種分歧會(huì)越來(lái)越大。
曾經(jīng)的最后通牒
之前在 2021 年 2 月時(shí),在 Go 官方博客上曾經(jīng)對(duì)此作出公示,給出最后的通牒:
圖片
- 可以通過(guò)將 GO111MODULE 環(huán)境變量設(shè)置為 off,仍然可以繼續(xù)在 GOPATH 模式下構(gòu)建包。
- 我們計(jì)劃在 Go1.17 中放棄對(duì) GOPATH 模式的支持。
- Go1.17 將忽略 GO111MODULE 環(huán)境變量。如果有未在模塊模式下構(gòu)建的項(xiàng)目,現(xiàn)在是遷移的時(shí)候了。
從結(jié)果來(lái)看,現(xiàn)在 2024 年了,大家也知道了,Go1.17 及以后也沒(méi)有放棄 GOPATH 模式。最后通牒是可以被打破的!
最終采取的策略和行動(dòng)
- 承諾無(wú)限期保留 GO111MODULE=off 時(shí),構(gòu)建 GOPATH 布局源代碼樹(shù)的功能。
- 在 GOPATH 模式下完全禁用 go get,因?yàn)樗艹晒ο螺d的代碼越來(lái)越少,帶來(lái)的開(kāi)發(fā)體驗(yàn)也越來(lái)越差。
- 在 GOPATH 模式下,將把 Go 語(yǔ)言版本假設(shè)為 Go1.21,而不是繼續(xù)假設(shè)為 “最新的 Go 版本”。這將確保如果在 Go 1.22 中更改 for 循環(huán)或在將來(lái)進(jìn)行其他重大更改時(shí),達(dá)到舊版代碼也能繼續(xù)編譯的目的。
總結(jié)
這次針對(duì) GOPATH 模式和 Module 模式的探討和推進(jìn),仍然是由 Go 核心團(tuán)隊(duì)負(fù)責(zé)人 rsc 負(fù)責(zé)發(fā)起。最終的結(jié)論是 GOPATH 模式這種歷史債務(wù)甩不掉,還是有人必須要使用的。但是我們也不能完全不管他。
答案是既要也要還要。所以對(duì) GOPATH 模式和 Module 模式同時(shí)做了一些小處理,避免造成過(guò)大的沖突。最終結(jié)論是:無(wú)限期保留基本 GOPATH 模式的支持。此項(xiàng)變更在 Go1.22 時(shí)已經(jīng)生效!