Go (golang) 已於 18 日釋出了 1.16 beta1 版本,至此其主體功能已經基本確定。我看大多數人都在關注 Go 在蘋果(Apple) M1 上的支援,甚至 Go 官方部落格中也有一篇專門的說明 Go on ARM and Beyond ,來介紹 Go 在此方面的支援。
我就不湊熱鬧了,我來聊聊 Go 1.16 中關於 go get
和 go install
你需要注意的地方。
目前 Docker 官方映象尚未釋出,我是本地構建了個映象來使用。
(MoeLove) ➜ go version
go version go1.16beta1 linux/amd64
概覽
Go 1.16 中包含著大量的 Modules 相關的更新,詳細內容可直接檢視其 Release Note。整體而言,包含以下要點:
GO111MODULE
預設為on
,如果要恢復到之前的行為,則需要將GO111MODULE
設定為auto
,這樣差不多意味著 GOPATH 模式要逐步淡出人們的視野了;go install
命令可以接受一個版本字尾了,(例如,go install sigs.k8s.io/kind@v0.9.0),並且它是在模組感知的模式下執行,可忽略當前目錄或上層目錄的go.mod
檔案。這對於在不影響主模組依賴的情況下,安裝二進位制很方便;- 在將來,
go install
被設計為“用於構建和安裝二進位制檔案”,go get
則被設計為 “用於編輯 go.mod 變更依賴”,並且使用時,應該與-d
引數共用,在將來版本中-d
可能會預設啟用; go build
和go test
預設情況下不再修改go.mod
和go.sum
。可通過go mod tidy
,go get
或者手動完成;
總結而言,關於 go install
和 go get
必須要注意的是:
基本上
go install <package>@<version>
是用於命令的全域性安裝:- 例如:
go install sigs.k8s.io/kind@v0.9.0
;
- 例如:
go get
安裝二進位制的功能,後續版本將會刪除;go get
主要被設計為修改go.mod
追加依賴之類的,但還存在類似go mod tidy
之類的命令,所以使用頻率可能不會很高;
Go 1.16 中已解決的工具安裝問題
到目前為止,Go 一直使用 go get
命令,將我們需要的工具安裝到 $GOPATH/bin
目錄下,但這種方式存在一個很嚴重的問題。go get
由於具備更改 go.mod
檔案的能力,因此我們 必須要避免執行 go get
命令時,讓它接觸到我們的 go.mod
檔案 ,否則它會將我們安裝的工具作為一個依賴。
目前的解決方案通常是:
(MoeLove) ➜ cd $(mktemp -d); GO111MODULE=on go get sigs.k8s.io/kind@v0.9.0
自 1.16 開始,我們可以直接使用下面的方式:
(MoeLove) ➜ go install sigs.k8s.io/kind@v0.9.0
非常的簡單直觀。需要注意的是 go install <package>@<version>
是從 1.16 開始增加的,無論你當前是否在一個模組下,此命令都會在 $GOPATH/bin
下安裝指定版本的工具。
此外由於 Go 1.16 中 GO111MODULE
預設是開啟的,go install
不會修改 go.mod
之類的檔案,不會造成任何意外。
注意:
@version
只能安裝主軟體包。非主程式包不受此格式約束。
關於不帶 @version
的 go install
- 在模組外,不帶
@version
是無法安裝的,會有如下錯誤:
(MoeLove) ➜ go install -v sigs.k8s.io/kind
go install: version is required when current directory is not in a module
Try 'go install sigs.k8s.io/kind@latest' to install the latest version
- 如果你在模組目錄中,並且你不帶
@version
執行安裝的話,只能安裝go.mod
中已經包含的版本。並且不能安裝未出現在go.mod
中的包。
(MoeLove) ➜ mkdir -p /go/src/github.com/moelove/iris
(MoeLove) ➜ cd /go/src/github.com/moelove/iris
# 初始化模組
(MoeLove) ➜ /go/src/github.com/moelove/iris go mod init
go: creating new go.mod: module github.com/moelove/iris
(MoeLove) ➜ /go/src/github.com/moelove/iris cat go.mod
module github.com/moelove/iris
go 1.16
# 不帶 @version 無法安裝
(MoeLove) ➜ /go/src/github.com/moelove/iris go install -v sigs.k8s.io/kind
no required module provides package sigs.k8s.io/kind; try 'go get -d sigs.k8s.io/kind' to add it
# 用 go get -d 下載
(MoeLove) ➜ /go/src/github.com/moelove/iris go get -d sigs.k8s.io/kind
go get: added sigs.k8s.io/kind v0.9.0
# 可以看到已經被新增到了模組依賴中
(MoeLove) ➜ /go/src/github.com/moelove/iris cat go.mod
module github.com/moelove/iris
go 1.16
require sigs.k8s.io/kind v0.9.0 // indirect
# 刪除本地的 kind 工具
(MoeLove) ➜ /go/src/github.com/moelove/iris which kind
/go/bin/kind
(MoeLove) ➜ /go/src/github.com/moelove/iris rm /go/bin/kind
(MoeLove) ➜ /go/src/github.com/moelove/iris which kind
# 不帶 @version 進行安裝
(MoeLove) ➜ /go/src/github.com/moelove/iris go install -v sigs.k8s.io/kind
(MoeLove) ➜ /go/src/github.com/moelove/iris which kind
/go/bin/kind
(MoeLove) ➜ /go/src/github.com/moelove/iris kind version
kind v0.9.0 go1.16beta1 linux/amd64
關於 go get
和 go.mod
go get
將二進位制安裝相關的功能都轉移到了 go install
, 僅作為用於編輯 go.mod
檔案的命令存在。在後續版本(計劃是 Go 1.17)中刪掉 go get
安裝二進位制的功能,接下來 go get
的行為就等同於我們現在執行 go get -d
命令了,僅需下載原始碼,並將依賴新增至 go.mod
即可。
go.mod
如何編輯
在 Go 1.16 中,另一個行為變更是 go build
和 go test
不會自動編輯 go.mod
了,基於以上資訊,Go 1.16 中將進行如下處理:
通過在程式碼中修改 import 語句,來修改
go.mod
:go get
可用於新增新模組;go mod tidy
刪除掉無用的模組;
將未匯入的模組寫入
go.mod
:go get <package>[@<version>]
;go mod tidy
也可以;- 手動編輯;
從 1.15 升級需要注意什麼?
由於 go build
和 go test
不會自動編輯 go.mod
了,所以可以將原本的行為通過 go mod tidy
共同處理。
總結
Go 1.16 中 go install
和 go get
方面有些不相容的變更,但是 1.16 中模組更加簡潔,減少了使用時的心智負擔,我還是很期待這個版本的。
歡迎訂閱我的文章公眾號【MoeLove】