緣起
最近編譯 GRPC 遇到了點坑,編譯各種報錯,經搜索調研發(fā)現(xiàn)用 mod 模式編譯時對版本要求1.13及以上,。比如我的 go1.12.4 就無法編譯,必須得 go1.13.xx 版本才能編譯。為了解決這種尷尬的場景只能再在主機安裝個 go1.13.xx 版本,那么有沒有什么優(yōu)雅的方式來實現(xiàn)本機多版本 Golang 版本的管理呢,能很方便的進行不同版本的切換,這也是本文的目的,推薦一款 Go多版本管理神器 gvm,用法類似 Python 的多版本管理工具 pyenv。
簡介
gvm,即 Go Version Manager,Go 版本管理器,使用 shell 腳本開發(fā),它可以非常輕量的切換 Go 版本。對比其他語言,通常也有類似的工具,如 NodeJS 的 NVM,Python 的 pyenv 等。在使用方法上和 Python 的多版本管理工具 pyenv 非常類似。
其實不借助類似的版本管理工具安裝多個版本 Go 也是可以自己手動實現(xiàn)的,做法很簡單,就是下載不同的 Golang 安裝包,然后放置到獨立的目錄,使用時將 GOROOT 和 GOPATH 指向對應版本的目錄即可完成版本切換。其實 gvm 原理上就是這么做的,只不過通過工具的形式將這些繁雜的手工操作封裝起來,使得開發(fā)起來更加優(yōu)雅,不必再為 Go 的安裝、版本管理花費更多的心思。下面為 gvm 的工作原理:

安裝
bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
輸出提示:
Cloning from https://github.com/moovweb/gvm.git to /Users/apple/.gvm
Created profile for existing install of Go at /usr/local/go
Installed GVM v1.0.22
Please restart your terminal session or to get started right away run
`source /Users/apple/.gvm/scripts/gvm`
安裝完成!
重啟控制臺或執(zhí)行 source $HOME/.gvm/scripts/gvm 即可啟用 gvm。
提醒下,不同操作系統(tǒng)還需要相應的依賴項要裝,具體查看 項目說明 的介紹。
安裝可能遇到的坑
$ gvm install go1.12.10
Downloading Go source...
ERROR: Couldn't download Go source. Check the logs /Users/jim/.gvm/logs/go-download.log
根據(jù)提示看 log 報錯
Cloning into '/Users/apple/.gvm/archive/go'...
error: RPC failed; curl 18 transfer closed with outstanding read data remaining
fatal: the remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed
解決問題:vim ~/.gvm/scripts/install
修改 GO_SOURCE_URL 變量地址為:
GO_SOURCE_URL=git://github.com/golang/go
使用
1.列出當前已安裝的 Go 版本
gvm list
2.列出當前可以安裝的 Go 版本
gvm listall
3.安裝指定版本的 Go
gvm install go1.12.10
4.切換到指定的 Go 版本
臨時切換
gvm use go1.12
永久切換
gvm use go1.12 --default
使用遇到的問題
當下次打開終端時,可能會出現(xiàn)zsh: command not found: gvm, 可以再在終端運行
source ~/.gvm/scripts/gvm
避免每次都要如此操作,可以
cat ~/.gvm/scripts/gvm
然后將上述文件中的內容加入~/.bashrc或~/.profile,然后使修改生效
cat ~/.gvm/scripts/gvm >> ~/.bashrc
source ~/.bashrc
或
cat ~/.gvm/scripts/gvm >> ~/.profile
source ~/.profile
包環(huán)境管理
gvm 除了 Go 版本的管理,還可以管理包環(huán)境,相關命令是 pkgenv 和 pkgset。如果沒使用包依賴管理工具,它也是挺方便的。
演示個例子,假設我們要創(chuàng)建一個新的項目 blog,可提前創(chuàng)建相應的環(huán)境。
$ gvm pkgset create blog # 創(chuàng)建
$ gvm pkgset use blog # 啟用
復制代碼現(xiàn)在,我們通過 go get 安裝的包都會默認在 blog 環(huán)境下?;诘脑硎?go get 默認會把安裝的放在 GOPATH 中的第一個目錄下。
好了,就介紹這么多吧。有興趣的朋友可以再研究研究。畢竟在有了 go mod 之后,這個功能以后是基本不會用了。
gvm 目錄結構
gvm 是 shell 編寫,默認是安裝在 $HOME/.gvm/ 目錄下。查看下它的目錄結構會有助我們了解它的實現(xiàn)。
其中幾個主要的目錄,如下:
archive # go 源碼
bin # gvm 可執(zhí)行文件
environments # 不同環(huán)境的環(huán)境變量配置
scripts # gvm 的子命令腳本
logs # 日志信息
pkgsets # 每個獨立環(huán)境 gopath 所在路徑
復制代碼在研究了 gvm 的實現(xiàn)后,我們會發(fā)現(xiàn),這一套思路其實也適用于其他很多工具的版本管理。如果之后再遇到同樣的需求,即使我們沒有現(xiàn)成的工具,自己實現(xiàn)一套也是可以的。
總結
本文從我的需求出發(fā),引出了如何靈活地進行管理 Go 版本的話題。
以往的經驗告訴我,既然其他語言都有工具實現(xiàn)這樣的需求,Go 也應該有。搜索了下,找到了 gvm。雖說我在使用它的時候,發(fā)現(xiàn)了一些 bug 與體驗不好的地方,但總體而言,已經足夠滿足我的需求。