如果你是一个 Golang 的用户,那么你大概率会遇到管理和维护 Golang 版本的诉求,如果你恰好同时需要开发调试两个不同版本的项目,在不考虑强制跳版本的情况下,你或许就需要使用“Golang 版本管理工具”来帮助你减轻负担了。

本篇文章将介绍最近几个月,我在使用的工具,它们的优势和不足。希望能够帮助到有类似需求的同学。

写在前面

在本地新旧项目并行开发的过程中,你大概率会遇到一个令人头疼的问题,如何同时使用两个不同版本的 Golang Runtime 进行开发呢?

docker run

但是在运行效率和复杂度上,相比本地环境而言,总归是高了那么一丢丢。那么有没有更节能环保的方式呢?

基于 Golang 的版本管理工具:voidint/g

gvm

如果你不希望自己编译安装,也可以用作者推荐的方式进行安装:

curl -sSL https://raw.githubusercontent.com/voidint/g/master/install.sh | bash
oh-my-zshg.zshrcunalias
echo "unalias g" >> ~/.zshrc # 可选。若其他程序(如'git')使用了'g'作为别名。
# 记得重启 shell ,或者重新 source 配置
~/.oh-my-zsh/plugins/git/git.plugin.zshg
# alias g='git'
.zshrc
# 我的 g 的bin目录调整到了 .gvm ,所以你可能需要一些额外的调整
export PATH="${HOME}/.gvm/bin:$PATH"
export GOROOT="${HOME}/.g/go"
export PATH="${HOME}/.g/go/bin:$PATH"
export G_MIRROR=https://gomirrors.org/
https://github.com/voidint/g/blob/master/cli/install.go
 fmt.Println("Checksums matched")

 // 删除可能存在的历史垃圾文件
 _ = os.RemoveAll(filepath.Join(versionsDir, "go"))

 // 解压安装包
 if err = archiver.Unarchive(filename, versionsDir); err != nil {
  return cli.NewExitError(errstring(err), 1)
 }
 // 目录重命名
 if err = os.Rename(filepath.Join(versionsDir, "go"), targetV); err != nil {
  return cli.NewExitError(errstring(err), 1)
 }
 // 重新建立软链接
 _ = os.Remove(goroot)

 if err := mkSymlink(targetV, goroot); err != nil {
  return cli.NewExitError(errstring(err), 1)
 }
 fmt.Printf("Now using go%s\n", v.Name)
 return nil
g
voidint/g

基于 BASH 的版本管理工具:gvm

gvmnvm
n
gvmgvm

不过,这些都是可解决的

gvm
  • 程序安装过程中遭遇失败
  • 下载 Golang 指定版本失败后无法继续安装
  • 用户不知道如何使用镜像资源

先来解决第一个问题,如何正确安装 gvm,官方 ReadMe 中的安装方式在 ZSH 环境中会遇到问题,推荐切换为下面的方式安装:

curl -sSL https://github.com/moovweb/gvm/raw/master/binscripts/gvm-installer | bash

执行过后,我们就可以看到正确的日志输出了:

Cloning from https://github.com/moovweb/gvm.git to /home/ubuntu/.gvm
No existing Go versions detected
Installed GVM v1.0.22

Please restart your terminal session or to get started right away run
 `source /home/ubuntu/.gvm/scripts/gvm`
gvm install go1.17.3 -B

解决这个问题其实也很简单,就是清除掉这个缓存内容:

rm -rf ~/.gvm/archive/go1.17.3.darwin-amd64.tar.gz
# or
rm -rf ~/.gvm/archive/

接着我们来看第三个问题,如何使用镜像地址进行下载,加速我们切换 Golang 版本的效率。在官方文档中,有一段使用介绍:

Usage: gvm install [version] [options]
    -s,  --source=SOURCE      Install Go from specified source.
...
https://github.com/moovweb/gvm/blob/master/scripts/install
...
 GO_SOURCE_URL=https://github.com/golang/go
 for i in "$@"; do
  case $i in
   -s=*|--source=*)
    GO_SOURCE_URL=$(echo "$i" | sed 's/[-a-zA-Z0-9]*=//')
   ;;
...
download_binary()
# `GO_BINARY_BASE_URL` env allow user setting base URL for binaries
 # download, e.g. "https://dl.google.com/go".
 GO_BINARY_BASE_URL=${GO_BINARY_BASE_URL:-"https://storage.googleapis.com/golang"}
 GO_BINARY_URL="${GO_BINARY_BASE_URL}/${GO_BINARY_FILE}"
 GO_BINARY_PATH=${GVM_ROOT}/archive/${GO_BINARY_FILE}

 if [ ! -f $GO_BINARY_PATH ]; then
  curl -s -f -L $GO_BINARY_URL > ${GO_BINARY_PATH}

  if [[ $? -ne 0 ]]; then
   display_error "Failed to download binary go"
   rm -rf $GO_INSTALL_ROOT
   rm -f $GO_BINARY_PATH
   exit 1
  fi
 fi
GO_BINARY_BASE_URL
rcgvm
export GO111MODULE=on
export GOPROXY=https://goproxy.io,direct
# or
# exort GOPROXY="https://goproxy.cn"
export GOPATH="$HOME/go"
PATH="$GOPATH/bin:$PATH"


export GO_BINARY_BASE_URL=https://golang.google.cn/dl/
[[ -s "$HOME/.gvm/scripts/gvm" ]] && source "$HOME/.gvm/scripts/gvm"
export GOROOT_BOOTSTRAP=$GOROOT

至于切换不同版本 Golang ,也很简单,只需要两条条命令:

gvm install go1.17.3 -B
gvm use go1.17.3
gvm

来自官方的解决方案:golang/dl

如果你不喜欢来自三方的解决方案,那么或许可以试试来自官方的方案。(前提是,你不需要同时运行多个版本的 Golang)

相比较社区方案,官方的方案就更有趣了:。官方维护了自 1.5 以来到 1.17 的所有版本的更新软件包。

我们可以通过安装普通软件包的方式来获取具体版本的安装工具,以及进行“覆盖安装”:

go get golang.org/dl/go1.17.3
go1.17.3 download
sdkexport
func goroot(version string) (string, error) {
 home, err := homedir()
 if err != nil {
  return "", fmt.Errorf("failed to get home directory: %v", err)
 }
 return filepath.Join(home, "sdk", version), nil
}

其他

此外,还有两个有趣的项目,借鉴自 Rustup 的 :;以及借鉴 rbenv和pyenv的:。

最后

最近在持续做笔记内容整理的事情,恰好看到这篇笔记草稿,顺手整理成文。

本篇就先写到这里啦,希望能够帮你节约一些时间,避过小坑。

--EOF


我们有一个小小的折腾群,里面聚集了几百位喜欢折腾的小伙伴。

在不发广告的情况下,我们在里面会一起聊聊软硬件、HomeLab、编程上的一些问题,也会在群里不定期的分享一些技术沙龙的资料。

喜欢折腾的小伙伴欢迎扫码添加好友。(添加好友,请备注实名,注明来源和目的,否则不会通过审核)


如果你觉得内容还算实用,欢迎点赞分享给你的朋友,在此谢过。


本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。