写了个零依赖的 Go 版本管理器,curl | bash 完事,支持自动回退国内镜像
为什么又造了个轮子
Go 多版本管理工具不少:gvm 9k+ star 但已停更归档,Apple Silicon 上 SSL 报错;g 轻量好用但需要用 Go 编译安装------我装版本管理器就是为了管理 Go,这成了鸡生蛋的问题;asdf 生态强大但太重,git + curl + 插件配置一套下来新手劝退。
我想要的其实很简单:打开终端,一行命令,装完就能用 。不需要装 Go、不需要 git、不需要 Homebrew。同时我在国内,下载 go.dev 时而抽风,希望镜像自动回退;AI 时代用 Claude Code / Cursor / Trae 写代码,IDE 不读 shell 配置的问题也最好能一并处理。
于是花了几个晚上写了 gv(Go Version) ------ 纯 bash 实现,零编译依赖,全平台可跑。
GitHub: github.com/EchoRealm-i... 安装:
curl -sSL https://raw.githubusercontent.com/EchoRealm-io/gv/main/install.sh | bash
技术选型:为什么是纯 bash
| 方案 | 优点 | 缺点 |
|---|---|---|
| Go 二进制 (g) | 性能好、原生 Windows | 需预装 Go 或下载 binary |
| Shell 函数 (gvm) | 零依赖 | PATH 注入复杂、已停更 |
| Shim 机制 (asdf/goenv) | 切换精确 | 启动开销大、配置复杂 |
| 纯 bash (gv) | 零依赖、透明、易调试 | 启动需 source 脚本 |
我选了纯 bash,核心考量就一个:降低安装门槛到极致 。用户不需要判断自己是 macOS arm64 还是 Linux amd64 去下对应的 binary,不需要配 GOPATH,不需要学新概念。curl | bash 是人类已知最低成本的软件分发方式。
代价是每次开终端要 source 3 个脚本文件(约 500 行 bash),实测启动开销 <20ms,可以接受。
架构设计
bash
~/.go-version-manager/
├── defaults.sh # 用户配置(安装目录、镜像、默认版本)
├── i18n.sh # 5 语言消息系统
├── core.sh # 核心函数(安装、切换、列表、镜像管理)
└── wrapper.sh # ~/bin/go 智能代理
~/bin/go # 替代系统 go 命令的 wrapper
/usr/local/go1.21.5/ # 各版本独立安装
/usr/local/go1.26.4/
版本切换链路
bash
用户输入 go build
→ ~/bin/go (wrapper)
→ 向上遍历查找 go.mod
→ 找到 go 1.21
→ 检查 /usr/local/go1.21.5 是否存在
→ 存在: exec /usr/local/go1.21.5/bin/go build
→ 不存在: 查找已安装的 1.21.x 任意版本
→ 找到: exec
→ 没找到: 提示安装,fallback 到默认版本
→ 没找到 go.mod: 使用 gv-use -g 持久化的版本
→ 没持久化: 使用 DEFAULT_GO_VERSION
多镜像回退链路
ini
_g fetch_go_versions()
→ mirrors.aliyun.com/?mode=json ← zh_CN 优先
→ 失败: mirrors.aliyun.com/ (HTML)
→ go.dev/?mode=json
→ go.dev/ (HTML 全量历史版本)
→ golang.google.cn/...
下载同理,每个源 10s 连接超时 + 120s 传输超时,失败自动下一个。
核心功能拆解
1. 五语言交互式安装
根据 $LANG 自动切换中文/繁体/日/韩/英。安装过程检测旧 Go、交互式删除、检测 shell 配置冲突、按文件清理注释行------每一步都有提示。
ruby
⚠️ 检测到现有的 Go 安装
路径:/usr/local/go
来源:system-installed
版本:go1.17.1
是否删除 /usr/local/go [Y/N]
> y
正在执行: sudo rm -rf /usr/local/go
✅ 已删除旧 Go
Go 安装目录[默认: /usr/local]:
> (回车)
...
2. 在线选版安装
bash
$ gv-install
$ curl -sSL https://mirrors.aliyun.com/golang/
← mirrors.aliyun.com (HTML) ← 展示实际调用的接口
1. 1.26
2. 1.25
...
> 1
1. 1.26.4
2. 1.26.3
...
> 1
$ curl -L ... -o /tmp/go1.26.4.darwin-arm64.tar.gz https://mirrors.aliyun.com/golang/go1.26.4.darwin-arm64.tar.gz
✅ 下载成功
💡 已切换到 Go 1.26.4(当前会话)
所有执行的 shell 命令都会打印出来,透明可控。
3. 命令设计
bash
gv-install # 交互式在线选版安装
gv-install 1.21 # 安装 1.21.x 最新补丁
gv-install 1.21.5 # 安装精确版本
gv-use 1.21.5 # 临时切换(仅当前终端)
gv-use -g 1.21.5 # 持久切换(新终端继承)
gv-list # 列出已安装版本
gv-mirror # 镜像列表
gv-mirror set <url> # 设为首选镜像
gv-mirror add <url> # 追加镜像
gv-help # 帮助
4. IDE 兼容处理
VSCode / Trae 等 GUI 应用不走 shell 配置,gv 安装时会提示:
VSCode / Trae 用户,请在 settings.json 中设置:
"go.goroot": "/usr/local/go1.26.4"
同时保留旧 GOROOT 配置作为 GUI fallback。
5. 完整卸载
bash
curl -sSL https://raw.githubusercontent.com/EchoRealm-io/gv/main/uninstall.sh | bash
自动清理:已安装 Go 版本 → gv 管理器文件 → shell 配置中的 source 行 → 被注释的旧配置。每个文件打印清理状态。
为什么要做 5 种语言
不是过度设计。Go 开发者在日本、韩国、台湾、香港都有大量分布,简体和繁体中文用户加起来可能超过英语用户。给每个开发者一个母语安装体验,比多加一个功能更有价值。
局限与改进方向
老实说,纯 bash 方案有天然的天花板:
- 无 SHA256 校验 --- 计划用
shasum -a 256从 go.dev 下载.sha256文件比对 - 不支持
.go-version文件 --- 目前只读go.mod,计划兼容 - 无 Windows 原生 --- 依赖 Git Bash/WSL,原生 PowerShell 版本需要重写
- 启动开销 --- source 脚本 ~20ms,二进制方案为 0。未来可考虑用 shc 编译安装后的脚本
| gv | g (voidint) | gvm | asdf | |
|---|---|---|---|---|
| 零依赖 | ✅ bash | ❌ 需 Go | ✅ | ❌ |
| go.mod 切换 | ✅ | ✅ .go-version | ✅ | ✅ |
| 多语言 UI | ✅ 5 种 | ❌ | ❌ | ❌ |
| 交互式选版 | ✅ | ❌ | ❌ | ❌ |
| 镜像自动回退 | ✅ | ❌ | ❌ | ❌ |
| 旧 Go 清理 | ✅ | ❌ | ❌ | ❌ |
| 卸载工具 | ✅ | ❌ | ❌ | ❌ |
| SHA256 校验 | ❌ | ✅ | ❌ | ✅ |
| Windows 原生 | ❌ | ✅ | ❌ | ⚠️ WSL |
| 启动速度 | ⚠️ ~20ms | ✅ ~1ms | ✅ ~1ms | ⚠️ ~80ms |
总结
gv 不是要取代 g 或 asdf,而是在"零门槛"这个细分场景做到极致。如果你经常在不同机器上临时装 Go、或者想给团队一个傻瓜式的多版本管理方案,试试看。
GitHub: github.com/EchoRealm-i... 安装:
curl -sSL https://raw.githubusercontent.com/EchoRealm-io/gv/main/install.sh | bash