如何靈活地進行 Go 版本管理

本文談下我對 Go 版本管理的一些思考,並給你們介紹一個小工具,gvm。這個話題提及來也很簡單,但若是想用的爽,仍是要稍微梳理下。git

背景介紹

Go 的版本管理,並不是包的依賴管理。平時的工做中,不少時候並不會遇到這樣的需求,因此可能並非很明白它的價值。github

簡單說下我寫這篇文章的背景吧。golang

最近幾周,Go 最重要的一則消息應該莫過 9月份 Go 1.13 的正式發佈。它的相關升級可查看 Go 1.13 正式發佈,看看都有哪些值得關注的特性 或官方 Go 1.13 Relase Notesweb

對於一名 gopher 而言,可能早已按捺不住本身那顆躁動的心,想盡快體驗下新版的升級項。但問題是,切換至新版 Go 一般會遇到一些問題,好比不一樣版本的環境配置,安裝的輔助工具和程序包在不一樣版本下可能會存在兼容或被覆蓋等問題。shell

我天然就但願有一套方案能夠幫助我完成 Go 版本的切換,實現不一樣版本間環境的徹底隔離。bash

思考方案

談到環境隔離,有不少方案可供選擇,如多主機、虛擬機、容器等技術。這些聽起來都挺不錯,都能實現需求。但若是隻是爲了 Go 版本管理,徹底能夠本身實現。網絡

多版本切換,主要是不一樣版本環境變量的隔離。Go 1.10 以前,咱們關心的變量有 GOROOT、GOPATH 和 PATH。Go 1.10 以後,GOROOT 已經默認爲 go 的當前安裝路徑,只要考慮 GOPATH 和 PATH 便可。session

最近,剛答過一個關於 Go 環境變量的問題,查看回答。其中對每一個變量的做用進行了比較細緻的描述。curl

如何實現

如今,我要實現我本身電腦上的兩個版本的 Go 自由切換,該如何作呢?工具

假設它們分別位於 ~/.goversions/sdk/ 目錄下的 go1.11/ 和 go1.13/。我如今要啓用 go 1.11,運行以下命令便可:

$ export PATH=~/.goversions/sdk/go1.11/bin/:$PATH

此時,GOROOT 已經自動識別,爲 ~/.goversions/sdk/go1.11/。Go 相關的工具鏈,源碼,標準庫都在這個目錄下。

但除 Go 自帶外,還有其餘第三方標準庫、編譯生成的庫文件等內容,它們都位於 GOPATH 下,若是不設置,默認爲 ~/go,在切換多版本的時候,就會產生混亂。咱們能夠爲每一個版本單獨設置個 GOPATH。

如 go1.11,設置 GOPATH 爲 ~/.goversions/gopath/go1.11-global/。

$ mkdir ~/.goversions/gopath/go1.11-global/
$ export GOPATH=~/.goversions/gopath/go1.11-global/

一個獨立的環境建立好了。

若是如今要切換至 go 1.13,幾個命令便可搞定。

$ export PATH=~/.goversions/sdk/go1.13/bin/:$PATH
$ mkdir -pv ~/.goversions/gopath/go1.13-global/
$ export GOPATH=~/.goversions/gopath/go1.13-global/

切換成功。

雖然,已經實現了需求,但總以爲用起來很是不爽。爲了操做方便,其實能夠把上面的思路提煉成 shell 腳本,整理成一套工具。

是否是蠢蠢欲動,想試一下?

但很遺憾,已經沒這個機會了,由於這個工具已經有人開發了,思路相似,但卻比這裏描述的要強,它就是 gvm, 地址 moovweb/gvm

什麼是 gvm

gvm,即 Go Version Manager,Go 版本管理器,它能夠很是輕量的切換 Go 版本。對比其餘語言,一般也有相似的工具,如 NodeJS 的 NVM,Python 的 virtualenv 等。

gvm 不只包含上面提到的版本切換,還能夠直接經過源碼編輯安裝任意版本的 Go,固然最好是 1.5 及以後版本,緣由後面解釋。

一件比較尷尬的點,gvm 產生背景並不是是爲了 Go 在不一樣版本間的切換,開發團隊當初開發這個工具主要爲了解決項目的依賴問題,經過切換環境實現包依賴的切換。下面,我會演示如何作到這一點。

但問題是,如今 Go 的依賴管理已經日趨完善,官方的 go module 也愈來愈好用,GOPATH 在被逐漸弱化,gvm 彷佛也就只剩下幫咱們快速體驗不一樣 Go 版本的功能還有點價值。

廢話說了那麼多,開始正式體驗下這個工具吧。

如何安裝

安裝很簡單,只要以下一行命令便可搞定。

$ bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)

輸出顯示:

Cloning from https://github.com/moovweb/gvm.git to /home/vagrant/.gvm
which: no go in (/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/vagrant/.local/bin:/home/vagrant/bin)
No existing Go versions detected
Installed gvm v1.0.22

Please restart your terminal session or to get started right away run
 `source /home/vagrant/.gvm/scripts/gvm`

安裝完成!

重啓控制檯或執行 source $HOME/.gvm/scripts/gvm 便可啓用 gvm。

提醒下,不一樣操做系統還須要相應的依賴項要裝,具體查看 項目說明 的介紹。 這裏面沒有提到 Windows,不知道可不可用。

gvm 安裝 Go

gvm 經過從 github 下載源碼編譯 Go 的安裝。而版本則是基於源碼中的 tag。由於 1.5 版本及以後,Go 已經實現了自編譯,於是要使用 gvm 安裝 Go,咱們要提早有可用的 Go 環境。

Go 的安裝能夠閱讀我以前的一篇文章 詳細聊聊如何安裝 Go,我認爲介紹的還算詳細。

Go 安裝完成,就可使用 gvm 隨意安裝切換任意版本的 Go 了。

$ gvm install go1.11

等待運行完成便可。

首次安裝的時間可能會比較久,主要取決於你的網絡,由於第一次須要從 github 下載源碼。

查看版本

首先,查看下個人系統已經安裝哪些 Go 版本有哪些吧,相關命令 gvm list。

$ gvm list

gvm gos (installed)

   go1.11
   go1.12
   go1.13
   go1.13beta1

安裝了 4 個版本,其中,go1.13beta1 是非穩定版本,因此說,若是咱們想盡快嘗試 go 的新特性,gvm 仍是很便捷的。

除了查看已安裝的版本,還能夠經過 gvm listall 查看全部版本,版原本源於源碼中的 tag 標籤。

$ gvm listall

gvm gos (available)

   go1
   go1.0.1
   go1.0.2
   go1.0.3
   go1.1

   ...

   go1.13
   go1.13beta1
   go1.13rc1
   go1.13rc2

但這個操做在 mac 上沒法執行,gvm 的實現中用到了 Linux 的 sort 命令,它與 mac 上的 sort 不兼容。

怎麼解決?

安裝個軟件 coreutils, 它之中有個 qsort 命令可用。經過 brew install coreutils 可直接安裝。而後,修改下文件 $HOME/.gvm/scripts/function/tool,將其中的 sort 修改成 qsort 便可。

選擇版本

選擇啓用的版本就很是簡單了。以下:

$ gvm use go1.11 [--default]

啓用成功後,能夠經過 go version 和 go env 確認下。若是想默認一個版本,加上 --default 設置便可。

包環境管理

gvm 除了 Go 版本的管理,還能夠管理包環境,相關命令是 pkgenv 和 pkgset。若是沒使用包依賴管理工具,它也是挺方便的。

演示個例子,假設咱們要建立一個新的項目 blog,可提早建立相應的環境。

$ gvm pkgset create blog  # 建立
$ gvm pkgset use blog     # 啓用

閒雜,咱們經過 go get 安裝的包都會默認在 blog 環境下。基於的原理是 go get 默認會把安裝的放在 GOPATH 中的第一個目錄下。

好了,就介紹這麼多吧。有興趣的朋友能夠再研究研究。畢竟在有了 go mod 以後,這個功能之後是基本不會用了。

gvm 目錄結構

gvm 是 shell 編寫,默認是安裝在 $HOME/.gvm/ 目錄下。查看下它的目錄結構會有助咱們瞭解它的實現。

其中幾個主要的目錄,以下:

archive             # go 源碼
bin                 # gvm 可執行文件
environments        # 不一樣環境的環境變量配置
scripts             # gvm 的子命令腳本
logs                # 日誌信息
pkgsets             # 每一個獨立環境 gopath 所在路徑

在研究了 gvm 的實現後,咱們會發現,這一套思路其實也適用於其餘不少工具的版本管理。若是以後再遇到一樣的需求,即便咱們沒有現成的工具,本身實現一套也是能夠的。

總結

本文從個人需求出發,引出瞭如何靈活地進行管理 Go 版本的話題。

以往的經驗告訴我,既然其餘語言都有工具實現這樣的需求,Go 也應該有。搜索了下,找到了 gvm。雖然說我在使用它的時候,發現了一些 bug 與體驗很差的地方,但整體而言,已經足夠知足個人需求。

參考

Go 語言多版本安裝及管理利器 - gvm
moovweb/gvm
gvm + go mod


歡迎關注個人公衆號!

相關文章
相關標籤/搜索