go 依赖包升级方法
3 min read

go 依赖包升级方法

go 依赖包升级方法
Photo by CDC / Unsplash

在维护一个有一定体量的 go 项目的时候,难免会碰到需要依赖包管理的问题。关于 go 的依赖包管理有很多不错的文章介绍How to Use Go Modules,这篇文章总结的是项目于中 go mod 依赖包升级的问题。

背景

go 项目中使用 go mod vendor 来离线管理所有的依赖包(主要是出于依赖版本锁定的目的),在项目日常管理中会涉及到几个跟依赖包升级的场景:

  1. 公共依赖包升级
  2. 私有依赖包升级

下面我们就分这两个场景来讨论。

公共依赖包升级

公共开源的依赖包升级相对比较简单,在 go 项目下执行:
go get -u github.com/xxx/xxx

更细致的还会有如下几种方式升级:

  • 升级到指定版本: go get -u github.com/xxx/xxx@v1.6.2
  • 升级到指定 commit 的版本:go get github.com/xxxx/xxx@q2516faf3

私有依赖包升级

升级私有库的方法逻辑跟公共依赖包是一致的,不过我在具体操作的时候踩了一个坑:

go: downloading gitlab.com/xxx v0.1.0 verifying gitlab.com/xxx@v0.1.0: github.com/alessiosavi/GoGPUtils@v0.0.9: reading https://sum.golang.org/lookup/gitlab.com/xxx@v0.1.0: 410 Gone

解决的方法是对环境变量进行设置(410 gone during go.mod import · Issue #35164 · golang/go):

go env -w GO111MODULE=on
go env -w GOPROXY=direct
go env -w GOSUMDB=off

前两个设置比较好理解:

  • GO111MODULE 启用 go module
  • GOPROXY module 托管站点代理

而真正导致私有模块有 410 Gone 报错的主要原是第三个 GOSUMDB,go module 启用时在本地建立一个 go.sum 文件,用来存储依赖包特定版本的加密校验值。同时,go 维护下载的软件包的缓存,并在下载时计算并记录每个软件包的加密校验值。在正常操作中,go 命令对照这些预先计算的校验和去检查某 repo 下的 go.sum 文件,而不是在每次命令调用时都重新计算它们。特定 module 版本的校验值永远不会改变,所以每次运行或构建时 go 命令都会通过本地的go.sum 去检查其本地缓存副本的校验值是否一致。如果校验值不匹配,则 go 命令将报告安全错误,并拒绝运行构建或运行。在这种情况下,重要的是找出正确的校验值,确定是 go.sum 错误还是下载的代码是错误的。如果 go.sum 中尚未包含已下载的module,并且该模块是公共 module,则 go 命令将查询 go 校验值数据库以获取正确的校验和数据存入 go.sum。如果下载的代码与校验值不匹配,则 go 命令将报告不匹配并退出。

go 1.13 提供了 GOSUMDB 环境变量用于配置 go 校验值数据库的服务地址(和公钥),其默认值为”sum.golang.org”,这也是 go 官方提供的校验值数据库服务(国内也可以使用sum.golang.google.cn,你懂的)。

根据 GOSUMDB 的原理接可以知道私有库的校验值在 GOSUMDB 中肯定是没有,这就导致了出现找不到的问题即 410 Gone 报错。所以一个快速的修复的方法就是关闭 GOSUMDB

References

  1. How to Use Go Modules | DigitalOcean
  2. go Module升级依赖以及设置网络代理_mayongze321的博客-CSDN博客_go 更新依赖
  3. Proposal: Secure the Public Go Module Ecosystem

Public discussion

足迹