在一臺機器上安裝並使用多版本的 Go ?

Python程式設計時光發表於2021-10-31

1. 需求背景

實際開發中會接觸到不同的開源專案,而這些專案有可能是不同團隊開發的,使用的 go 版本都是不一樣的。

以我為例,最近在研究 KubeVirt (一個能在 K8S 下管理虛擬機器的開源專案),為了實現自己的需求,需要對 KubeVirt 進行二次開發。

通過 go.mod 得知 KubeVirt 是使用 go 1.13 開發的,而同時為了能在 KubeVirt 下的虛擬機器能使用 LVM 這種儲存方式,我們又引入了阿里研發的 lvm-csi 外掛,同樣的,這個外掛已經實現的功能距離我們的預期還有點差距,因此同樣要進行二次開發。檢視 go.mod 發現,lvm-csi 是在更老的版本下開發的,也就是 go 1.12 。

而同時我的機器上很早之前就安裝過 go 1.14 的版本,也一直使用它來開發。

問題就來了,如何讓才能在我的機器上能同時安裝這麼多個版本的 golang ,而且互不衝突呢?

2. 安裝多版本的 Go

要想不同版本的 go 互不衝突,只要將他們安裝在不同的目錄下就可以了。

首先下載兩個版本的安裝包

$ wget https://dl.google.com/go/go1.12.linux-amd64.tar.gz
$ wget https://dl.google.com/go/go1.13.linux-amd64.tar.gz

然後分別解壓至不同目錄

# 解壓go 1.12
sudo tar -C /tmp/ -xzf go1.12.linux-amd64.tar.gz
mv /tmp/go /usr/local/go12 

# 解壓go 1.13
sudo tar -C /tmp/  -xzf go1.13.linux-amd64.tar.gz
mv /tmp/go /usr/local/go13

3. 簡單粗暴的方案

在同一臺機器中安裝多個版本的 Golang 需要注意

  • 區分不同版本的 go 入口
  • 切換使用不同的環境變數

區分不同版本 go 入口

當你在環境中有多個 go ,那麼當你使用 go build 等命令時,系統如何知道你想要使用的是哪個版本呢?

系統並不知道,因此你需要為不同版本的 go 起不同的名字

  • go 1.12 的 go 入口就改成 /usr/local/go12/bin/go12
  • go 1.13 的 go 入口就改成 /usr/local/go13/bin/go13
  • 以此列推

如此一來,就不會混淆了

$ go12 version
go version go1.12 linux/amd64
$ go13 version
go version go1.13 linux/amd64

切換使用不同的環境變數

使用了不同的go入口,對應的環境變數也要變數,比如 GOROOT,它可不會隨著你使用哪個版本的 go 就自動切換,看下面他們輸出的都是一個值。

$ go12 env GOROOT
/usr/local/go
$ go13 env GOROOT
/usr/local/go

因此,這個切換不同環境變數得自己來做

另外要注意的是

  1. go 1.12 沒有 go env -w 中的 -w 引數
  2. go 1.13 中雖然有 -w 但不能覆蓋OS級別的環境變數,修改前需先 unset

知道了這幾點之後,便可以自行實現切換的方案。

我想的方案是可以在 /usr/local/go13/bin/ 寫一個修改環境變數的指令碼

$ cat << EOF >/usr/local/go12/bin/goto12
unset GOROOT
go env -w GOROOT="/usr/local/go12/"
EOF

$ chmod +x /usr/local/go12/bin/goto12

下次要使用 go 1.12 的時候,直接使用下面命令就可以修改環境變數

$ source goto12

go 1.13 也是同理,不敢贅述。

實現的效果如下

$ go env GOROOT
/usr/local/go

$ source goto12
$ go12 env GOROOT
/usr/local/go12

$source goto13
$ go13 env GOROOT
/usr/local/go13

4. 比上面更優的方案

到這裡,你應該已經感受到了,每次切換都要手動 source 一下,還是有點麻煩。

其實我還有一個更好的方法,這種方案,可以不用去改 go 入口的名字,同樣連 source 都不用。

只要執行下面兩條件命令即可(每個版本兩條,兩個版本就是四條)

$ cat << EOF >/usr/local/go12/bin/go12
unset GOROOT
go env -w GOROOT="/usr/local/go12/"
/usr/local/go12/bin/go $@
EOF

$ chmod + /usr/local/go12/bin/go12

$ cat << EOF >/usr/local/go13/bin/go13
unset GOROOT
go env -w GOROOT="/usr/local/go13/"
/usr/local/go13/bin/go $@
EOF

$ chmod + /usr/local/go13/bin/go13

如果一來,當你執行 go12 就會自動修改 go12 的環境變數,執行 go13 就會自動修改 go13 的環境變數,並且不會影響預設的 go 的行為。

當然以上我都只改了 GOROOT 這一環境變數,若在不同的 go 版本還有其他不一樣的地方,可以繼續在 go12 或者go13 中新增對應的 shell 程式碼。

絮叨一下

我在 SegmentFault 上寫過很多的 Python 相關文章,其中包括 Python 實用工具,Python 高效技巧,PyCharm 使用技巧,很高興得到了很多知乎朋友的認可和支援。

在他們的鼓勵之下,我將過往文章分門別類整理成三本 PDF 電子書

PyCharm 中文指南

《PyCharm 中文指南》使用 300 多張 GIF 動態圖的形式,詳細講解了最貼合實際開發的 105個 PyCharm 高效使用技巧,內容通俗易懂,適合所有 Python 開發者。

線上體驗地址:https://pycharm.iswbm.com

Python 黑魔法指南

《Python黑魔法指南》目前迎來了 v3.0 的版本,囊集了 100 多個開發小技巧,非常適合在閒時進行碎片閱讀。

線上體驗地址:https://magic.iswbm.com

Python 中文指南

學 Python 最好的學習資料永遠是 Python 官方文件,可惜現在的官方文件大都是英文,雖然有中文的翻譯版了,但是進度實在堪憂。為了照顧英文不好的同學,我自己寫了一份 面向零基礎的朋友 的線上 Python 文件 -- 《Python中文指南》

線上體驗地址:https://python.iswbm.com

有幫助的話,記得幫 點個贊喲~

相關文章