Go 部落格
Go 1.16 中新的模組變更
我們希望您喜歡 Go 1.16!這個版本有許多新功能,尤其是模組的部分。發行說明 對這些變更做了簡短描述,不過讓我們深入探討其中幾個吧。
預設啟用模組
現在 go
指令預設會在模組感知模式中建置套件,即使沒有 go.mod
也一樣。這是朝所有專案都使用模組邁出一大步。
您仍舊可以透過將 GO111MODULE
環境變數設為 off
來在 GOPATH 模式中建置套件。您也可以將 GO111MODULE
設為 auto
,使其只在當前目錄或任何母目錄存在 go.mod 檔案時才啟用模組感知模式。這之前是預設設定。請注意,您可以使用 go env -w
永久設定 GO111MODULE
和其他變數。
go env -w GO111MODULE=auto
我們計畫在 Go 1.17 中停止支援 GOPATH 模式。換句話說,Go 1.17 將會忽略 GO111MODULE
。如果您有無法在模組感知模式中建置的專案,現在是進行遷移的時候了。如果有任何問題妨礙您進行遷移,請考慮提交 問題 或 回饋報告。
不自動變更 go.mod 和 go.sum
先前,當 go
指令在 go.mod
或 go.sum
中發現問題,例如缺少 require
指令或缺少 total 金額,它會嘗試自動修復問題。我們收到許多反饋意見,認為這種行為令人驚訝,尤其是對通常沒有副作用的指令,例如 go list
。自動修復並不總是好用的:如果任何必需模組沒有提供已匯入套件,go
指令將會新增新的依賴項,可能導致常見依賴項昇級。即使拼寫匯入路徑錯誤,也會導致網路查詢 (失敗)。
在 Go 1.16 中,具有模組意識的指令在發現 go.mod
或 go.sum
的問題後,會回報錯誤,而非嘗試自動修復問題。在多數情況下,錯誤訊息會建議使用指令來修復問題。
$ go build
example.go:3:8: no required module provides package golang.org/x/net/html; to add it:
go get golang.org/x/net/html
$ go get golang.org/x/net/html
$ go build
和以前相同,如果 vendor
目錄存在,go
指令可以使用該目錄 (有關詳細資訊,請參閱 提供)。由於 go get
和 go mod tidy
指令的主要目的是管理依賴項,因此它們仍會修改 go.mod
和 go.sum
。
安裝特定版本的執行檔
go install
指令現在可以透過指定 @version
字尾,在特定版本安裝執行檔。
go install golang.org/x/tools/gopls@v0.6.5
當使用此語法時,go install
會從那個確切的模組版本安裝指令,並忽略目前目錄和父目錄中的任何 go.mod
檔案。(未指定 @version
字尾時,go install
會繼續照先前方式執行,使用目前模組的 go.mod
中列出的版本需求和替換項來建置程式。)
我們之前建議使用 go get -u program
安裝執行檔,但這個用法讓 go get
的意義產生許多混淆,因為它在 go.mod
中加入或變更模組版本需求。而且,為了避免意外修改 go.mod
,人們開始建議更複雜的指令,例如
cd $HOME; GO111MODULE=on go get program@latest
現在我們所有人都可以使用 go install program@latest
代替。有關詳細資訊,請參閱 go install
。
為了消除使用此安裝語法時所使用的版本二義性,對程式 go.mod
檔案中可能出現的指令施加了一些限制。特別是,目前不允許使用 替換
和 排除
指令。長期而言,一旦新的 go install program@version
對足夠多的使用案例正常運作後,我們計畫讓 go get
停止安裝指令二進位檔。有關詳細資訊,請參閱 問題 43684。
模組撤回
你是否曾經在元件版本尚未準備好之前意外發佈?或者在你發佈版本後馬上發現一個需要快速修正的問題?已發佈版本的錯誤很難修正。為了保持元件建置具有確定性,版本在發佈後就無法修改。即使你刪除或變更版本標籤,proxy.golang.org
和其他代理程式可能已經快取原始檔案。
元件作者現在可以使用 go.mod
中的 retract
指令撤回元件版本。已撤回的版本仍然存在且可以下載(因此依賴它的建置不會崩毀),但 go
指令在解析版本(例如 @latest
)時不會自動選取它。go get
和 go list -m -u
會對現有使用狀況列印警告訊息。
例如,假設熱門函式庫 example.com/lib
的作者發佈版本 v1.0.5
,然後發現了一個新的安全性問題。他們可以在自己的 go.mod
檔案中新增一個指令,如下所示
// Remote-triggered crash in package foo. See CVE-2021-01234.
retract v1.0.5
接著,作者可以標記並發佈版本 v1.0.6
,也就是新的最高版本。在那之後,已經依賴於 v1.0.5
的使用者在檢查更新或升級相依套件時會收到此版本的撤回通知。通知訊息可能會包含 retract
指令上方註解中的文字。
$ go list -m -u all
example.com/lib v1.0.0 (retracted)
$ go get .
go: warning: example.com/lib@v1.0.5: retracted by module author:
Remote-triggered crash in package foo. See CVE-2021-01234.
go: to switch to the latest unretracted version, run:
go get example.com/lib@latest
請查看 撤回元件版本,取得一個互動式瀏覽器導覽指南,並了解 play-with-go.dev。詳情請參閱 retract
指令說明文件 的語法部分。
使用 GOVCS 控制版本控制工具
go
指令可以從鏡像網站(例如 proxy.golang.org)或直接使用 git
、hg
、svn
、bzr
或 fossil
從版本控制存放庫下載元件原始碼。直接存取版本控制很重要,尤其是對於並未在代理程式上提供的私人元件,但這也可能造成安全問題:版本控制工具中的錯誤可能被惡意伺服器利用來執行非預期的程式碼。
Go 1.16 有一個新的設定變數 GOVCS
,讓使用者可以指定允許使用特定版本控制工具的元件。GOVCS
接受由逗號分隔的 pattern:vcslist
規則清單。pattern
是一個 path.Match
樣式,用於比對元件路徑的一個或多個開頭元素。特殊樣式 public
和 private
分別比對公開和私人元件(private
定義為比對 GOPRIVATE
樣式中模式的元件;public
則為其他所有內容)。vcslist
是允許版本控制指令的管線分隔清單,或者關鍵字 all
或 off
。
例如
GOVCS=github.com:git,evil.com:off,*:git|hg
在此設定中,可以透過 `git` 下載 `github.com` 路徑上的模組;無法透過任何版本控制命令下載 `evil.com` 路徑上的模組,且所有其他路徑(`*` 符合所有路徑)可以使用 `git` 或 `hg` 下載。
如果未設定 `GOVCS`,或如果模組不符合任何模式,`go` 命令會使用此預設值:允許公共模組使用 `git` 和 `hg`,並允許私密模組使用所有工具。允許僅使用 Git 和 Mercurial 的原理是,這兩個系統最常注意作為不可信伺服器的用戶端執行的議題。相較之下,Bazaar、Fossil 和 Subversion 主要用在可信的驗證環境中,而且作為攻擊面,審查程度不高。也就是說,預設設定是
GOVCS=public:git|hg,private:all
詳情請參閱 使用 `GOVCS` 控制版本控制工具。
接下來要做什麼?
我們希望您覺得這些功能好用。我們已經努力開發 Go 1.17 的下一組模組功能,特別是 懶惰模組加載,這項功能應可加快模組加載處理速度並增加穩定性。不變的是,如果您遇到新錯誤,請在 問題追蹤器 上告知我們。編碼愉快!
下一篇文章:Context 和結構
上一篇文章:Go 1.16 發布
部落格索引