# 一次 Go Mod Tidy 卡住与 Unknown Revision 的踩坑记录


最近在维护一个 Go 项目时，遇到了一个关于 `go mod tidy` 的棘手问题。表面现象很简单：执行命令后，终端要么卡在下载某个包的过程中一动不动，要么直接报错 `unknown revision`。

这个报错看起来像是版本号写错了，但真正麻烦的地方在于，它背后可能隐藏着一连串问题——网络、代理、间接依赖、版本冲突，每个环节都有可能出问题。

这篇文章把这次完整的排查过程记录下来，重点讲四件事：

1. 问题是怎么开始的
2. 网络和代理层面排查了哪些
3. 版本冲突是怎么发现的
4. 最终用什么方案解决

<!--more-->

## 1. 问题是怎么发现的

这次问题不是项目编译报错，也不是代码逻辑有 bug，而是出现在一个看似很常规的操作上——整理 Go 模块依赖。

当时执行：

```bash
go mod tidy
```
结果终端卡住了，停留在：

```txt
go: downloading golang.org/x/arch v0.8.0
```
然后就没有然后了，进度条不动，命令行也不返回。

一开始以为只是网络慢，多等了一会儿，发现它干脆就不走了。按 Ctrl+C 中断后重新执行，结果这次卡在了另一个包上：

```txt
go: downloading github.com/aws/aws-sdk-go-v2/service/sts v1.30.3
```
还是超时。

这时候基本可以判断，不是某个包本身的问题，而是整个下载链路出了状况。

## 2. 第一步排查：GOPROXY 配置
对于 Go 模块下载慢或卡住的问题，第一反应就是检查 GOPROXY 环境变量。

执行：

```bash
go env GOPROXY
```
输出是空的，或者指向了默认的 https://proxy.golang.org，这个域名在国内访问确实不稳定。

于是先配置了国内代理：

```bash
go env -w GOPROXY=https://goproxy.cn,direct
go env -w GOSUMDB=off
```
配置完成后，再次执行 go mod tidy。这次确实有进展，不再卡在 golang.org/x/arch 了，但新的问题很快出现——下载 github.com/mattn/go-sqlite3 时又卡住了。

## 3. 第二步排查：Git 代理问题
这时候已经不是单纯的 Go 代理能解决的了。因为 go get 在下载某些包时，会直接调用 Git 命令去拉取仓库，而 Git 有自己的网络配置。

为了看清楚卡在哪里，加上了 -x 参数，打印详细执行过程：

```bash
go get -x github.com/mattn/go-sqlite3@latest
```
输出显示，Go 已经成功发送了 HTTP 请求并收到了 200 OK：

```txt
# get https://github.com/mattn/go-sqlite3: 200 OK (1.038s)
```
但命令并没有结束，一直卡着。

这时候怀疑是 Git 本身的问题。检查 Git 代理配置：

```bash
git config --global --get http.proxy
```
果然，输出是：

```txt
http://127.0.0.1:7890
```
这个地址看起来是 Clash 或 v2ray 等代理工具的默认端口，但当时代理工具并没有运行，所以 Git 尝试通过一个不存在的代理去连接 GitHub，结果就是一直在等待连接建立。

解决方法很简单，移除无效的 Git 代理：

```bash
git config --global --unset http.proxy
git config --global --unset https.proxy
```
再次执行 go get，网络层面的问题总算解决了，下载速度也恢复了正常。

但没过多久，一个新的报错出现了。

## 4. 第三步排查：unknown revision 版本错误
网络问题解决后，执行 go mod tidy，终端输出了这样一段错误：

```txt
go: github.com/astaxie/beego@v1.12.3 requires
    github.com/mattn/go-sqlite3@v2.0.3+incompatible: 
    reading github.com/mattn/go-sqlite3/go.mod at revision v2.0.3: 
    unknown revision v2.0.3
```
这个报错的意思是：某个依赖（astaxie/beego@v1.12.3）要求使用 go-sqlite3 的 v2.0.3 版本，但 go-sqlite3 这个仓库里根本不存在这个版本。

这其实是一个典型的上游依赖版本配置错误——某个库的 go.mod 文件里声明了一个不存在的依赖版本。

这时候排查的方向已经从“网络问题”转到了“依赖版本冲突”。

## 5. 第四步排查：找出是谁引入了问题版本
首先，确认这个 astaxie/beego 是不是项目直接依赖的：

```bash
go mod why github.com/astaxie/beego
```
输出：

```txt
# github.com/astaxie/beego
(main module does not need package github.com/astaxie/beego)
```
说明它不是直接依赖，而是某个间接依赖引入的。

继续查找是谁引用了它：

```bash
go mod why -m github.com/astaxie/beego
```
这次找到了完整的依赖链：

```txt
# github.com/astaxie/beego
gin-vben-admin/internal/service
github.com/rongcloud/server-sdk-go/v3/sdk
github.com/astaxie/beego/httplib
原来是 rongcloud/server-sdk-go 这个 SDK 内部使用了 astaxie/beego/httplib，而 astaxie/beego@v1.12.3 又错误地依赖了 go-sqlite3@v2.0.3+incompatible。
```
项目本身的 go.mod 里用的是新版的 github.com/beego/beego v1.12.14，但间接依赖却拉取到了旧版的 astaxie/beego@v1.12.3，于是触发了这个 unknown revision 错误。

## 6. 最终解决方案：replace 指令
问题的根源明确后，解决思路就清晰了：

不存在的版本无法下载，但可以通过 replace 指令，把它重定向到一个真实存在的版本。

在 go.mod 文件末尾添加：

```go
replace github.com/mattn/go-sqlite3 v2.0.3+incompatible => github.com/mattn/go-sqlite3 v1.14.24
```
这条指令的作用是：

当 Go 模块系统遇到 github.com/mattn/go-sqlite3@v2.0.3+incompatible 时，自动把它替换成 github.com/mattn/go-sqlite3@v1.14.24。

v1.14.24 是 go-sqlite3 仓库中真实存在的最新稳定版本。

添加后，执行：

```bash
go clean -modcache
go mod tidy
```
这次没有再报错，命令顺利执行完成。

## 7. 为什么不直接替换 beego
在排查过程中，曾经尝试过这样写：

```go
replace github.com/astaxie/beego v1.12.3 => github.com/beego/beego v1.12.14
```
但会报错：

```txt
go: github.com/beego/beego@v1.12.14 used for two different module paths 
    (github.com/astaxie/beego and github.com/beego/beego)
```
Go 模块系统不允许同一个模块路径被两个不同的模块名同时使用。因为项目中已经有 github.com/beego/beego 了，再通过 replace 把 astaxie/beego 指向它，就会产生路径冲突。

所以最终的方案是：只替换那个不存在的版本，而不是替换整个模块。

## 8. 这次排查里几个最有价值的经验
### 8.1. go mod tidy 卡住，不一定是网络慢
很多时候第一反应是网络问题，但如果配置了 GOPROXY 后依然卡住，需要考虑 Git 自身的代理设置。

### 8.2. 200 OK 不代表下载完成
go get -x 输出里的 200 OK 只是 HTTP 请求成功了，不代表整个下载过程结束。如果 Git 代理配置有问题，依然会卡在后面的环节。

### 8.3. unknown revision 通常是版本不存在
这个错误很直白，就是某个版本在仓库里不存在。但更隐蔽的情况是：它是由一个间接依赖引入的，需要顺着依赖链往上找。

### 8.4. replace 是解决上游版本错误的有效手段
当某个依赖声明了不存在的版本时，replace 指令可以把它重定向到正确的版本，而不需要修改上游仓库的代码。

## 9. 最后的结论
这次问题的完整链路是：

网络层：GOPROXY 未配置，加上 Git 代理指向了无效地址，导致下载卡住

依赖层：rongcloud/server-sdk-go 间接引入了 astaxie/beego@v1.12.3

版本层：astaxie/beego@v1.12.3 依赖了不存在的 go-sqlite3@v2.0.3+incompatible

解决方式：先用 replace 修复版本冲突，再结合 GOPROXY 和 Git 配置解决网络问题

最终有效的配置是：

```bash
# 环境变量
go env -w GOPROXY=https://goproxy.cn,direct
go env -w GOSUMDB=off
go
// go.mod
replace github.com/mattn/go-sqlite3 v2.0.3+incompatible => github.com/mattn/go-sqlite3 v1.14.24
```
如果你之后也遇到 go mod tidy 卡住或报 unknown revision 的情况，可以按这个顺序排查：

检查 GOPROXY 是否配置正确

检查 Git 代理是否生效（git config --global --get http.proxy）

用 go mod why -m 定位是谁引入了问题版本

用 replace 指令将不存在的版本重定向到正确版本

希望这次记录能帮你少踩一些坑。

---

> 作者: kayoon  
> URL: https://iamky.cn/posts/go/go-mod-tidy-troubleshooting/  

