背景
通过 go mod
管理依赖包, 其中有几个依赖是私有仓库的, 之前下载下来没有问题。 最近刚把 Go 版本升级到13, 发现拉不下来,报 410 Gone 。(其实这个报错跟 HTTP Code 410 的语义是一样的,表示资源的访问在源服务器上不再可用 )
详细错误类似如下:
go get -v bitbucket.org/compay/lucifer
go: finding bitbucket.org/compay/lucifer latest
go: downloading bitbucket.org/compay/lucifer v0.0.0-20190921175342-61a76c096369
verifying bitbucket.org/compay/lucifer@v0.0.0-20190921175342-61a76c096369: bitbucket.org/compay/lucifer@v0.0.0-20190921175342-61a76c096369: reading https://sum.golang.org/lookup/bitbucket.org/compay/lucifer@v0.0.0-20190921175342-61a76c096369: 410 Gone
问题分析
在网上找了资料, 发现确实跟 Go 的版本升级有关系。
问题的根本原因在于 Go1.13版本之后, 对 Modules 的机制做了变更。 GOPROXY 现在可以设置为以逗号分隔的代理 URL 列表,或特殊标记 direct,其默认值是 https://proxy.golang.org,direct
。 当解析一个包的路径到它所所在模块时,go 命令会在列表中的每个代理服务器上连续尝试所有候选模块路径。如果代理服务器无法到达,或出现404或410以外的HTTP状态码,则会终止搜索,而不会请求其余代理服务器。
新引入了 GOPRIVATE 环境变量。 它定义不对外公开的模块路径,作为低级别的 GONOPROXY 和 GONOSUMDB 变量的默认值。而这两个变量提供了代理和通过 checksum database
进行验证的能力。
解决
有两种解决办法, 一是通过 GOPRIVATE 环境变量走内部代理, 二是通过 GONOSUMDB 环境变量。
使用 GOPRIVATE
上面已经说了, 如果代理服务器无法到达, 比如访问 410 Gone 出错, 就从 GOPRIVATE 定义的代理服务器列表, 尝试继续下载依赖包。可以在自己的 ~/.bashrc
(或者 ~/.zshrc
) 里, 添加以下命令 :
export GOPRIVATE="gitlab.com/idmabar,bitbucket.org/idmabar,github.com/idmabar"
然后再通过 go get
尝试重新拉包:
$ go get bitbucket.org/company/lucifer
go: finding bitbucket.org/company/lucifer latest
go: downloading bitbucket.org/company/lucifer v0.0.0-20190921175342-61a76c096369
go: extracting bitbucket.org/company/lucifer v0.0.0-20190921175342-61a76c096369
使用 GONOSUMDB
没有做过尝试, 具体可以参考这篇论文: Proposal: Secure the Public Go Module Ecosystem
简单来讲, 就是定义 GONOSUMDB 变量:
export GONOSUMDB="gitlab.com/idmabar,bitbucket.org/idmabar,github.com/idmabar"
总结
本文整理了如何解决 go mod
下载依赖报410 Gone 错误的问题。 这个问题只在 Go1.13 版本之后引入的, 所以在升级系统上一些软件后, 发现行为表现跟之前不一样,或者运行出错, 大概率是软件的变更引起的。 实际上线上的故障绝大部分也是变更引起的, 对应变更引起的问题, 需要更快地找到变更的点或者发现, 以快速响应。
参考
- go modules in version 1.13
- Proposal: Secure the Public Go Module Ecosystem
- go private repo - answer from Stackoverflow
- Provying a checksum dateabase API
有疑问加站长微信联系(非本文作者)