新買了 Apple M1 Mac,卻不知道如何安裝 Go?
點(diǎn)擊上方“Go編程時(shí)光”,選擇“加為星標(biāo)”

前些天有一位朋友問(wèn)我:

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

比如 Apple macOS,下載后雙擊打開(kāi),按提示操作即可。
然而,最新版 Mac 沒(méi)有使用 Intel 芯片,而是使用了自研的 M1 芯片。之前 Intel 芯片是 amd64 架構(gòu),而 M1 芯片是 arm64 結(jié)構(gòu)。前面說(shuō)了,雖然 Go 是支持 arm64 架構(gòu)的,但并非操作系統(tǒng)和 CPU 架構(gòu)的任意組合都支持,也就是說(shuō) GOOS=darwin,GOARCH=arm64 的組合不支持(或者說(shuō)沒(méi)有針對(duì)這個(gè)用于 Mac 的組合做處理)。因此,現(xiàn)有預(yù)編譯的版本都沒(méi)法安裝到 M1 Mac 上。
02 探討解決方案
要解決這個(gè)問(wèn)題,當(dāng)然前提是 Go 團(tuán)隊(duì)支持 M1。雖然 Go 以往的版本都不支持,但對(duì) M1 的支持,Go 已經(jīng)開(kāi)發(fā)完畢,而且網(wǎng)上已經(jīng)有了 Intel 和 M1 的性能測(cè)試。
Go 標(biāo)準(zhǔn)庫(kù)性能測(cè)試,對(duì)比 Intel 和 蘋果 M1 處理器[1] Hugo 在 Apple M1 的性能測(cè)試[2]
對(duì) M1 的支持,需要等到 Go1.16 發(fā)布,也就是明年 2 月份。但我們可以通過(guò) Go 代碼倉(cāng)庫(kù)的 master 分支來(lái)編譯安裝 Go,因?yàn)樗侵С?M1 的(注意,因?yàn)槭情_(kāi)發(fā)版本,請(qǐng)勿用于生產(chǎn)環(huán)境)。
現(xiàn)在引出另一個(gè)問(wèn)題:因?yàn)?Go 自 1.5 開(kāi)始實(shí)現(xiàn)了自舉,如果從源碼安裝 Go,需要本地有 Go 的編譯器。。。陷入了死循環(huán)。
如果是非 M1 芯片,通常的做法是:下載一份 Go1.4 版本代碼,編譯一個(gè) Go1.4(因?yàn)樗?C 語(yǔ)言實(shí)現(xiàn)的,不依賴 Go)。然后用這個(gè) Go1.4 編譯最新的 Go 源碼。
實(shí)際上,官方告訴你有四種方法處理這種情況。
源碼安裝的四種方法
下載 Go 的最新二進(jìn)制版本(其實(shí)可以不是最新的); 在一臺(tái)安裝有 Go 的電腦上執(zhí)行交叉編譯; 使用 gccgo; 即上面提到的方法,編譯一個(gè) Go1.4,然后用它編譯其他 Go 版本;
更多詳細(xì)信息參考官方文檔:https://docs.studygolang.com/doc/install/source#go14。
所以,對(duì)于 M1 芯片安裝 Go,方法 1 和方法 4 行不通(Go 1.4 很顯然不支持 M1 芯片),而使用交叉編譯是一個(gè)不錯(cuò)的選擇,畢竟 gccgo,很多人并不熟悉。
03 通過(guò)交叉編譯在 M1 上安裝 Go
我認(rèn)為支持交叉編譯是 Go 的一大特色,不僅支持交叉編譯 Go 程序,本身也支持交叉編譯。
現(xiàn)在就講解通過(guò)交叉編譯解決 M1 安裝 Go 的問(wèn)題。
1)下載 Go 最新源碼。
在一臺(tái)非 M1 電腦上,下載 Go 最新源碼,假設(shè)下載到用戶目錄:
$?cd?~
$?git?clone?https://github.com/golang/go
2)進(jìn)行交叉編譯
$?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
從上面的輸出可以看到,在用戶目錄下會(huì)生成 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 總結(jié)
吃螃蟹嘛,應(yīng)該有一定的心里準(zhǔn)備。但 Go 還是很給力。Bradfitz 發(fā)推文說(shuō),蘋果在 6 月 22 日說(shuō),會(huì)給 Go 支持 Apple Silicon (arm64) 提交 patch,但到目前為止沒(méi)看到,至少?zèng)]有在郵件組中出現(xiàn),他們沒(méi)有在 https://tip.golang.org/CONTRIBUTORS 列表中。所有支持 Apple Silicon 的工作都是 Go 社區(qū)做的。
買了 M1 還沒(méi)裝 Go 的,可以試試了!
參考資料
Go 標(biāo)準(zhǔn)庫(kù)性能測(cè)試,對(duì)比 Intel 和 蘋果 M1 處理器: https://roland.zone/m1-go-benchmarks/
[2]Hugo 在 Apple M1 的性能測(cè)試: https://gohugo.io/news/hugo-macos-intel-vs-arm/

???
