GVM(Go版本管理器)通过简单的GOPATH管理,维持多个Go环境,包括版本和模块。
【译文】原文地址
GVM(Go版本管理器)是一个开源工具用于管理Go环境。支持安装多个Go版本并在项目中使用GVM”pkgsets“管理各模块。最开始由 Josh Bussdieker开发,GVM和Ruby的RVM类似允许您为每个项目或每组项目创建一个开发环境,将不同的Go版本和模块进行分离,更灵活并且避免版本问题。
Go模块管理有好几个选择,包括go1.11引入的Modules。但我发现GVM更简单和直接,即使我不使用它来管理包,我也可以用它来管理Go版本。
安装GVM
GVM安装很简单。GVM 库安装文档引导你下载安装脚本并通过管道传入bash执行:
bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
尽管越来越多的人采用这种安装方法,但在安装之前看看安装程序具体做了什么仍然是一个很好的做法。安装脚本具体执行工作:
1、检查一些依赖
2、克隆GVM库
3、使用shell脚本:
- 安装Go
- 管理GOPATH环境变量
- 在bashrc、zshrc、或profile中添加一行配置
如果你想双击查看具体做了什么,你可以克隆repo并阅读shell脚本,然后执行./binscript/gvm-installer使用本地脚本配置。
注意:GVM可能用于下载和编译新的Go版本,因此需要一些依赖如Make、Git和Curl。你可以在GVM的README中找到完整依赖列表
使用GVM安装和管理Go版本
一旦安装了GVM,您就可以开始使用它来安装和管理不同版本的Go。gvm listall命令显示可以下载和编译Go的可用版本:
[chris@marvin ]$ gvm listall
$ gvm listall
gvm gos (available)
go1
go1.0.1
go1.0.2
go1.0.3
<output truncated>
安装特定的Go版本,只需执行下gvm install <go version>这么简单,go version就是前面gvm listall列出的版本其中之一。
假如你现在有个项目使用Go1.12.8版本。你可以使用gvm install go1.12.8命令安装。
[chris@marvin]$ gvm install go1.12.8
Installing go1.12.8...
* Compiling...
go1.12.8 successfully installed!
在终端上输入gvm list,可以看到Go 1.12.8版本已经安装到系统中(使用你的操作系统的包管理器打包的版本)
[chris@marvin]$ gvm list
gvm gos (installed)
go1.12.8
=> system
GVM仍然使用Go的系统版本,用它旁边的=>符号表示。你可以通过gvm use命令切换你的环境来使用新安装的go1.12.8:
[chris@marvin]$ gvm use go1.12.8
Now using version go1.12.8
[chris@marvin]$ go version
go version go1.12.8 linux/amd64
GVM使得管理Go的安装版本变得非常简单,而且会变得更好!
使用GVM pkgset
Go使用开箱即用方式管理包和模块。默认情况下,如果你执行go get包,会将对应的包下载到$GOPATH的src和pkg目录。然后就可以使用import导入到Go程序里。这种方式使包的获取很简单,尤其是对没有特权的用户,不需要执行sudo来获取root权限。但是,在不同的项目中管理相同包的不同版本是很困难的。
有很多方法可以尝试解决或缓解这个问题,包括后来引入的Go Module和go dep。在我发现GVM之前,我会在不同的Docker容器中构建和测试不同Go项目,以确保隔离。
GVM通过使用“pkgsets”,根据安装的Go版本在默认的PATH一样。
很容易理解其中的工作原理。首先安装一个新的Go版本,v1.12.9:
[chris@marvin]$ echo $GOPATH
/home/chris/.gvm/pkgsets/go1.12.8/global
[chris@marvin]$ gvm install go1.12.9
Installing go1.12.9...
* Compiling...
go1.12.9 successfully installed
[chris@marvin]$ gvm use go1.12.9
Now using version go1.12.9
当GVM被告知使用一个新版本时,它会切换到新的$GOPATH,它对应于该版本的默认全局pkgset:
[chris@marvin]$ echo $GOPATH
/home/chris/.gvm/pkgsets/go1.12.9/global
[chris@marvin]$ gvm pkgset list
gvm go package sets (go1.12.9)
=> global
全局pkgset中的包可用在对应Go版本的任何项目中,尽管默认情况下没有安装额外的包。
假如你开始一个新的项目,需要一个特定的包。首先使用GVM来创建新的pkgset命名为:introToGvm:
[chris@marvin]$ gvm pkgset create introToGvm
[chris@marvin]$ gvm pkgset use introToGvm
Now using version go1.12.9@introToGvm
[chris@marvin]$ gvm pkgset list
gvm go package sets (go1.12.9)
global
=> introToGvm
如上所述,为pkgset在$GOPATH前面添加新的目录:
[chris@marvin]$ echo $GOPATH
/home/chris/.gvm/pkgsets/go1.12.9/introToGvm:/home/chris/.gvm/pkgsets/go1.12.9/global
将目录切换到introToGvm路径,检查目录结构——可以使用awk和bash完成这个有趣的过程:
[chris@marvin]$ cd $( awk -F':' '{print $1}' <<< $GOPATH )
[chris@marvin]$ pwd
/home/chris/.gvm/pkgsets/go1.12.9/introToGvm
[chris@marvin]$ ls
overlay pkg src
注意,新目录看起来很像一个普通的$GOPATH。新的Go包可以用Go get命令下载,它们被添加到pkgset中。
作为一个例子,使用以下方法获取gorilla/mux包,然后检查pkgset的目录结构:
[chris@marvin]$ go get github.com/gorilla/mux
[chris@marvin]$ tree
[chris@marvin introToGvm ]$ tree
.
├── overlay
│ ├── bin
│ └── lib
│ └── pkgconfig
├── pkg
│ └── linux_amd64
│ └── github.com
│ └── gorilla
│ └── mux.a
src/
└── github.com
└── gorilla
└── mux
├── AUTHORS
├── bench_test.go
├── context.go
├── context_test.go
├── doc.go
├── example_authentication_middleware_test.go
├── example_cors_method_middleware_test.go
├── example_route_test.go
├── go.mod
├── LICENSE
├── middleware.go
├── middleware_test.go
├── mux.go
├── mux_test.go
├── old_test.go
├── README.md
├── regexp.go
├── route.go
└── test_helpers.go
如您所见,gorilla/mux如预期一样被添加到pkgset $GOPATH目录中,现在可以在项目中使用这个pkgset。
GVM使Go管理变得简单
GVM以一种直观和非侵入性的方式对Go版本和包进行管理。它可以单独使用,也可以与其他Go模块管理技术结合使用,并利用GVM的Go版本管理功能。通过Go版本和包依赖分离使项目开发更容易,并减少了管理版本冲突的复杂性,GVM使这一切变得轻而易举。