新買了 Apple M1 Mac,卻不知道如何安裝 Go?
點擊上方“Go編程時光”,選擇“加為星標”

前些天有一位朋友問我:

有些朋友可能會有點奇怪,M1 有什么特別的嗎?為了照顧部分童鞋,這里簡單介紹下。
01 為什么會出現(xiàn)這個問題
大家知道不同的操作系統(tǒng)是很不一樣的,同時不同的 CPU 架構也是很不一樣的。Go 號稱是跨平臺的,自然要支持這些操作系統(tǒng)和 CPU 架構。
在 Go 中,GOOS 表示操作系統(tǒng),GOARCH 表示 CPU 架構。比如你的 Linux 服務器,一般是 GOOS=linux,GOARCH=amd64(即 x86-64);你現(xiàn)在的 Mac 很可能是 GOOS=darwin,GOARCH=amd64 等。這里定義了 Go 支持的操作系統(tǒng)和 CPU 架構:https://docs.studygolang.com/pkg/runtime/internal/sys/#pkg-constants。當然,這里的 GOOS 和 GOARCH 并非任意組合都支持。
一般地,很多人安裝 Go,通過網上下載編譯好的、對應系統(tǒng)的包,比如到 https://studygolang.com/dl 可以下載你需要的文件,常見的系統(tǒng)是:Linux、Mac 和 Windows。

比如 Apple macOS,下載后雙擊打開,按提示操作即可。
然而,最新版 Mac 沒有使用 Intel 芯片,而是使用了自研的 M1 芯片。之前 Intel 芯片是 amd64 架構,而 M1 芯片是 arm64 結構。前面說了,雖然 Go 是支持 arm64 架構的,但并非操作系統(tǒng)和 CPU 架構的任意組合都支持,也就是說 GOOS=darwin,GOARCH=arm64 的組合不支持(或者說沒有針對這個用于 Mac 的組合做處理)。因此,現(xiàn)有預編譯的版本都沒法安裝到 M1 Mac 上。
02 探討解決方案
要解決這個問題,當然前提是 Go 團隊支持 M1。雖然 Go 以往的版本都不支持,但對 M1 的支持,Go 已經開發(fā)完畢,而且網上已經有了 Intel 和 M1 的性能測試。
Go 標準庫性能測試,對比 Intel 和 蘋果 M1 處理器[1] Hugo 在 Apple M1 的性能測試[2]
對 M1 的支持,需要等到 Go1.16 發(fā)布,也就是明年 2 月份。但我們可以通過 Go 代碼倉庫的 master 分支來編譯安裝 Go,因為它是支持 M1 的(注意,因為是開發(fā)版本,請勿用于生產環(huán)境)。
現(xiàn)在引出另一個問題:因為 Go 自 1.5 開始實現(xiàn)了自舉,如果從源碼安裝 Go,需要本地有 Go 的編譯器。。。陷入了死循環(huán)。
如果是非 M1 芯片,通常的做法是:下載一份 Go1.4 版本代碼,編譯一個 Go1.4(因為它是 C 語言實現(xiàn)的,不依賴 Go)。然后用這個 Go1.4 編譯最新的 Go 源碼。
實際上,官方告訴你有四種方法處理這種情況。
源碼安裝的四種方法
下載 Go 的最新二進制版本(其實可以不是最新的); 在一臺安裝有 Go 的電腦上執(zhí)行交叉編譯; 使用 gccgo; 即上面提到的方法,編譯一個 Go1.4,然后用它編譯其他 Go 版本;
更多詳細信息參考官方文檔:https://docs.studygolang.com/doc/install/source#go14。
所以,對于 M1 芯片安裝 Go,方法 1 和方法 4 行不通(Go 1.4 很顯然不支持 M1 芯片),而使用交叉編譯是一個不錯的選擇,畢竟 gccgo,很多人并不熟悉。
03 通過交叉編譯在 M1 上安裝 Go
我認為支持交叉編譯是 Go 的一大特色,不僅支持交叉編譯 Go 程序,本身也支持交叉編譯。
現(xiàn)在就講解通過交叉編譯解決 M1 安裝 Go 的問題。
1)下載 Go 最新源碼。
在一臺非 M1 電腦上,下載 Go 最新源碼,假設下載到用戶目錄:
$?cd?~
$?git?clone?https://github.com/golang/go
2)進行交叉編譯
$?cd?go/src
$?GOOS=darwin?GOARCH=arm64?./bootstrap.bash
####?Copying?to?../../go-darwin-arm64-bootstrap
####?Cleaning?../../go-darwin-arm64-bootstrap
Removing?VERSION.cache
Removing?bin/
Removing?pkg/
Removing?src/cmd/cgo/zdefaultcc.go
Removing?src/cmd/go/internal/cfg/zdefaultcc.go
Removing?src/cmd/go/internal/cfg/zosarch.go
Removing?src/cmd/internal/objabi/zbootstrap.go
Removing?src/go/build/zcgo.go
Removing?src/runtime/internal/sys/zversion.go
####?Building?../../go-darwin-arm64-bootstrap
Building?Go?cmd/dist?using?/Users/xuxinhua/go1.4.?(go1.4-bootstrap-20170531?darwin/amd64)
Building?Go?toolchain1?using?/Users/xuxinhua/go1.4.
Building?Go?bootstrap?cmd/go?(go_bootstrap)?using?Go?toolchain1.
Building?Go?toolchain2?using?go_bootstrap?and?Go?toolchain1.
Building?Go?toolchain3?using?go_bootstrap?and?Go?toolchain2.
Building?packages?and?commands?for?host,?darwin/amd64.
Building?packages?and?commands?for?target,?darwin/arm64.
----
Bootstrap?toolchain?for?darwin/arm64?installed?in?/Users/xuxinhua/go-darwin-arm64-bootstrap.
Building?tbz.
-rw-r--r--??1?xuxinhua??staff??128102136?12?16?17:15?/Users/xuxinhua/go-darwin-arm64-bootstrap.tbz
從上面的輸出可以看到,在用戶目錄下會生成 go-darwin-arm64-bootstrap 文件夾和 go-darwin-arm64-bootstrap.tbz 壓縮包,將其中之一發(fā)送給 M1 Mac,在 M1 電腦上可以以此作為 bootstrap,重新編譯 Go,也可以直接將它作為 Go 編譯器使用。
$?cd?~/go-darwin-arm64-bootstrap
$?bin/go?env????
GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="~/Library/Caches/go-build"
GOENV="~/Library/Application?Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="~/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="~/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="~/go-darwin-arm64-bootstrap"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="~/Downloads/go-darwin-arm64-bootstrap/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="devel?+5a25a3fd1d?Tue?Dec?15?02:35:59?2020?+0000"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g?-O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g?-O2"
CGO_FFLAGS="-g?-O2"
CGO_LDFLAGS="-g?-O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC?-pthread?-fno-caret-diagnostics?-Qunused-arguments?-fmessage-length=0?-fdebug-prefix-map=/var/folders/6r/nghqxtb92kv5136s7k67_cc00000gn/T/go-build4293620280=/tmp/go-build?-gno-record-gcc-switches?-fno-common"
04 總結
吃螃蟹嘛,應該有一定的心里準備。但 Go 還是很給力。Bradfitz 發(fā)推文說,蘋果在 6 月 22 日說,會給 Go 支持 Apple Silicon (arm64) 提交 patch,但到目前為止沒看到,至少沒有在郵件組中出現(xiàn),他們沒有在 https://tip.golang.org/CONTRIBUTORS 列表中。所有支持 Apple Silicon 的工作都是 Go 社區(qū)做的。
買了 M1 還沒裝 Go 的,可以試試了!
參考資料
Go 標準庫性能測試,對比 Intel 和 蘋果 M1 處理器: https://roland.zone/m1-go-benchmarks/
[2]Hugo 在 Apple M1 的性能測試: https://gohugo.io/news/hugo-macos-intel-vs-arm/

???
