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
。如果您有專案尚未在模組感知模式下構建,現在是遷移的時候了。如果存在阻止您遷移的問題,請考慮提交一個 issue 或一份 體驗報告。
go.mod 和 go.sum 不再自動更改
以前,當 go
命令發現 go.mod
或 go.sum
中存在問題(例如缺失的 require
指令或缺失的 checksum)時,它會嘗試自動修復問題。我們收到了很多反饋,認為這種行為令人意外,特別是對於像 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
命令可能會使用它(詳情請參閱 Vendoring)。像 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 install program@latest
。詳情請參閱 go install
。
為了消除關於使用哪個版本的歧義,在使用此安裝語法時,程式 go.mod
檔案中允許存在的指令有一些限制。特別是,目前不允許使用 replace
和 exclude
指令。從長遠來看,一旦新的 go install program@version
在足夠多的用例中執行良好,我們計劃讓 go get
停止安裝命令二進位制檔案。詳情請參閱 issue 43684。
模組撤回
您是否曾不小心在模組版本尚未準備好之前釋出了它?或者在釋出某個版本後立即發現了需要快速修復的問題?已釋出的版本中的錯誤很難糾正。為了保持模組構建的確定性,版本釋出後不能修改。即使您刪除或更改版本標籤,proxy.golang.org
和其他代理很可能已經快取了原始版本。
模組作者現在可以使用 go.mod
中的 retract
指令來 撤回 模組版本。被撤回的版本仍然存在且可以下載(因此依賴它的構建不會中斷),但 go
命令在解析像 @latest
這樣的版本時不會自動選擇它。go get
和 go list -m -u
會列印關於現有使用的警告。
// Remote-triggered crash in package foo. See CVE-2021-01234.
retract v1.0.5
例如,假設流行庫 example.com/lib
的作者釋出了 v1.0.5
,然後發現了一個新的安全問題。他們可以在其 go.mod
檔案中新增一個指令,如下所示
$ 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
指令文件。
接下來,作者可以標記並推送版本 v1.0.6
,這是新的最高版本。在此之後,已經依賴於 v1.0.5
的使用者在檢查更新或升級依賴包時會收到撤回的通知。通知訊息可能包含 retract
指令上方註釋中的文字。
對於互動式的、基於瀏覽器的指南,請檢視 play-with-go.dev 上的撤回模組版本。有關語法詳情,請參閱 retract
指令文件。
使用 GOVCS 控制版本控制工具
go
命令可以從像 proxy.golang.org 這樣的映象或直接使用 git
、hg
、svn
、bzr
或 fossil
從版本控制倉庫下載模組原始碼。直接訪問版本控制非常重要,特別是對於在代理上不可用的私有模組,但它也可能是一個安全問題:版本控制工具中的錯誤可能被惡意伺服器利用來執行非預期的程式碼。
GOVCS=github.com:git,evil.com:off,*:git|hg
Go 1.16 引入了一個新的配置變數 GOVCS
,它允許使用者指定哪些模組允許使用特定的版本控制工具。GOVCS
接受一個逗號分隔的 pattern:vcslist
規則列表。pattern
是一個 path.Match
模式,匹配模組路徑的一個或多個前導元素。特殊模式 public
和 private
分別匹配公共模組和私有模組(private
定義為與 GOPRIVATE
中的模式匹配的模組;public
是其他所有模組)。vcslist
是允許的版本控制命令的管道分隔列表,或者關鍵字 all
或 off
。
例如
GOVCS=public:git|hg,private:all
有關詳情,請參閱 使用 GOVCS
控制版本控制工具。
透過此設定,路徑位於 github.com
的模組可以使用 git
下載;路徑位於 evil.com
的模組不能使用任何版本控制命令下載;所有其他路徑(*
匹配所有)可以使用 git
或 hg
下載。
如果未設定 GOVCS
,或者模組不匹配任何模式,go
命令將使用此預設設定:允許公共模組使用 git
和 hg
,允許私有模組使用所有工具。僅允許 Git 和 Mercurial 的理由是,這兩個系統作為不受信任伺服器的客戶端執行時,其安全性問題受到了最多的關注。相比之下,Bazaar、Fossil 和 Subversion 主要用於受信任、經過身份驗證的環境,並且作為攻擊面的審查不夠充分。也就是說,預設設定是
下一篇文章:上下文和結構體
詳情請參閱 使用 GOVCS
控制版本控制工具。
接下來是什麼?