01
介绍
在使用 Go 开发项目时,通常我们会遇到关于 Go 版本的一些问题,比如:公司的旧项目使用的低版本 Go 开发,新项目使用的高版本 Go 开发。
或者,公司的 Go 项目使用的低版本 Go 开发,我们想要学习 Go 新版本的一些新特性。
总之,我们就是有使用不同 Go 版本开发项目的需求。
本文给读者朋友们推荐的是 Go 版本管理器 gvm[1],使用 gvm 可以非常方便切换 Go 开发环境的 Go 版本。
02
安装
我的本地开发环境是 macOS 系统,以 macOS 为例,安装 gvm 的步骤如下:
执行命令:
brew install bison
需要注意的是,通常在 macOS 中,已存在 bison
,可以执行命令 which bison
检查,如果不存在,再使用 macOS 软件包管理器 Homebrew[3] 安装。
执行命令:
bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
需要注意的是,如果你使用的不是 bash
,请更改为你使用的 shell,比如你使用的 zsh
,只需把 bash
改为 zsh
。
安装完之后,在你的 ~/.bashrc
或 ~/.zshrc
中添加以下命令:
[[ -s "$HOME/.gvm/scripts/gvm" ]] && source "$HOME/.gvm/scripts/gvm"
然后,执行命令 source ~/.bashrc
或 source ~/.zshrc
。
执行命令:
gvm version
输出结果:
Go Version Manager v1.0.22 installed at /Users/frank/.gvm
如果可以输出 gvm 的版本号,说明已成功安装 gvm。
需要注意的是,如果你使用的不是 macOS,而是 Linux 发行版 Ubuntu 或者 Centos 等,请参考官方文档,安装所需的依赖。
03
基础使用方式
在安装 gvm 之后,我们可以执行 gvm
查看 gvm 支持的命令。
安装 go:
首先,我们可以执行命令 gvm listall
查看 gvm 收录的 Go 版本,然后,我们可以执行命令 gvm install go1.24.4
安装指定 Go 版本。
选择 go:
安装多个 Go 版本之后,我们可以执行命令 go use go1.24.4
选择使用的 Go 版本。
卸载 go:
如果我们想要卸载某个不再需要的 Go 版本,我们可以执行命令 go uninatll go1.24.1
,但是,需要注意的是,我们需要先执行命令 gvm use go1.24.1 && go clean -modcache
,然后,再执行命令 gvm uninstall go1.24.1
删除 Go 版本。
04
进阶使用方式 - pkgset
在掌握了基础使用方式之后,我们再聊聊进阶使用方式 - 包集(pkgset)机制。
当我们使用 gvm use go1.24.4
选择 Go 版本之后,执行命令 echo $GOPATH
,输出结果是 /Users/frank/.gvm/pkgsets/go1.24.4/global
。
进入 GOPATH 目录 cd $GOPATH
,执行命令 ls -l
,输出 overly
,该目录包含 2 个子目录,分别是 bin
和 lib
。
cd $GOPATH
tree
.
└── overlay
├── bin
└── lib
└── pkgconfig
实际上,这就是 gvm 的包集(pkgset)机制,默认创建全局包集 global,作为默认包集,该路径作为环境变量 GOPATH。
我们在该路径下创建 src 目录,用于存放 Go 代码。
其中,包集路径下的子目录 overlay
的作用是作为环境变量 GOBIN,比如执行命令 go install
或 go build -o
生成二进制文件时,gvm 会将路径 /Users/frank/.gvm/pkgsets/go1.24.4/global/overlay/bin
作为环境变量 GOBIN。
另外一个作用是存放我们安装的自定义工具,比如 easyjson
。
比如,当我们需要使用不同版本的工具(比如 easyjson
)时,我们可以使用 gvm 的包集(pkgset)机制,创建不同的包集,安装不同版本的自定义工具。
我们可以使用 gvm 的子命令 pkgset
管理 Go 包。
gvm 创建包集(pkgset):
gvm pkgset create mypkg
gvm 选择包集(pkgset):
gvm pkgset use mypkg
Now using pkgset go1.24.4@mypkg
列出所有包集(pkgset):
gvm pkgset list
gvm go package sets (go1.24.4)
global
=> mypkg
通过 gvm 的包集机制,使我们在同一台机器上,可以维护多个版本的 Go 和多个版本的工具。使不同版本的 Go 完全隔离它们的包和依赖。
05
进阶使用方式 - .gvmrc
我们前面讲的都是执行 gvm 命令的方式,使用 gvm 管理 Go 版本和包集,实际上还可以使用 .gvmrc
配置文件的方式。
GOPATH 模式
以 GOPATH 模式的项目为例,Go 项目的目录结构:
~/.gvm/
└── pkgsets/
└── go1.24.4/
└── myproject/ <-- gvm 的 pkgset: GOPATH 根目录
├── overlay/ <-- go install 安装的工具
├── pkg/ <-- 编译后缓存包
└── src/ <-- GOPATH 模式项目代码都放这里
└── github.com/
└── yourname/
└── yourproject/
├── .gvmrc
├── main.go
└── util/
└── helper.go
.gvmrc
项目级配置文件:
.gvmrc
配置文件的示例内容:
# go1.24.4
go1.24.4@myproject
其中,go1.24.4
表示指定项目使用的 Go 版本;go1.24.4@myproject
表示指定项目使用的 Go 版本和包集。
使用方式:.gvmrc
配置文件并不会自动生效,需要进入项目目录中,执行命令 gvm pkgset use
。
需要注意的是,一般我们会把 .gvmrc
文件放在项目目录的根目录中,但是,也可以放在其它目录中,执行命令 gvm pkgset use -f path/to/.gvmrc
,通过 -f
选项指定 .gvmrc
的路径。
Go Modules 模式
实际上,在 go v1.11 开始,社区开始推荐使用 Go Modules 模式,不建议继续使用 GOPATH 模式。
以 Go Modules 模式为例,Go 项目的目录结构:
~/code/myapp/ <-- 项目根目录
│
├── .gvmrc <-- 指定使用的 Go 版本和 pkgset(如 go1.24.4@mypkg)
├── go.mod <-- Go modules 项目
├── go.sum
│
├── cmd/ <-- 程序入口目录(main.go 通常放在这里)
│ └── myapp/
│ └── main.go
│
├── internal/ <-- 项目私有代码
│ └── config/
│ └── config.go
│
├── pkg/ <-- 可复用的库代码
│ └── util/
│ └── string.go
│
├── api/ <-- 接口定义、protobuf 或 OpenAPI 等
│ └── proto/
│ └── service.proto
│
├── scripts/ <-- 脚本目录,比如构建/部署脚本
│ └── build.sh
│
├── README.md
└── Makefile <-- 推荐添加 Makefile 简化常用操作
我们可以发现,.gvmrc
配置文件在 Go Modules 模式的 Go 项目的根目录。
同样,我们进入项目目录之后,通过执行命令 gvm pkgset use
读取 .gvmrc
中的配置信息。
06
总结
本文我们介绍怎么使用 Go 版本管理器 gvm 在同一台机器上维护多个版本的 Go 和多个版本的工具。
读者朋友们如果也有该需求,推荐大家试用一下 gvm。
需要注意的是,gvm 不支持 Windows,使用 Windows 的读者朋友们,可以选择其它版本管理器,比如 g
和 asdf
等。
参考资料
[1]
Go 版本管理器 gvm: https://github.com/moovweb/gvm
[2]
解析生成器 Bison: https://www.gnu.org/software/bison/
[3]
macOS 软件包管理器 Homebrew: https://brew.sh/