惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hacker News: Ask HN
Hacker News: Ask HN
H
Help Net Security
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog RSS Feed
Jina AI
Jina AI
Stack Overflow Blog
Stack Overflow Blog
量子位
博客园_首页
Vercel News
Vercel News
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Forbes - Security
Forbes - Security
IT之家
IT之家
N
News and Events Feed by Topic
S
Security Affairs
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Webroot Blog
Webroot Blog
Recorded Future
Recorded Future
L
LangChain Blog
Y
Y Combinator Blog
AI
AI
MyScale Blog
MyScale Blog
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
Know Your Adversary
Know Your Adversary
AWS News Blog
AWS News Blog
Help Net Security
Help Net Security
Cyberwarzone
Cyberwarzone
L
Lohrmann on Cybersecurity
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Google Online Security Blog
Google Online Security Blog
V2EX - 技术
V2EX - 技术
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
PCI Perspectives
PCI Perspectives
I
Intezer
T
Tenable Blog
G
Google Developers Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
Troy Hunt's Blog
L
LINUX DO - 最新话题
云风的 BLOG
云风的 BLOG
C
CXSECURITY Database RSS Feed - CXSecurity.com
有赞技术团队
有赞技术团队
O
OpenAI News
P
Proofpoint News Feed
TaoSecurity Blog
TaoSecurity Blog
C
Check Point Blog
Last Week in AI
Last Week in AI
S
Schneier on Security
Simon Willison's Weblog
Simon Willison's Weblog
Blog — PlanetScale
Blog — PlanetScale

Razeen`s Blog

Let's Encrypt 推出 Gen Y 根证书架构:揭示 Web PKI 的五大未来趋势 通过 Wi-Fi 自动备份你的 iPhone 到 Nas 管理培训感悟:从技术视角看管理之路 UPS 一拖多:保护你的 NAS 和 Linux 服务器 从影音中心到 AI 助手:我的50款 Homelab 服务清单 从SSL证书有效期将缩短到47天聊开去 部署一个自己的 Running Page 谈谈特斯拉 Model Y 用车一年的感受和费用分析 弃用 Disqus 评论,使用自建 Waline 使用 Prometheus 和 Grafana 搭建你的证书监控面板 服务器迁移记:一次磁盘换板引发的Linux分区与挂载的学习 改善信息来源, 利用 RSS 高效获取资讯 (RSShub + Reeder5 + WeWe RSS) 多种 Docker 镜像拉取解决方案与实践 App分享 | AppCleaner - Mac上的卸载神器 Azure OpenAI API 申请和使用 如何开通 OneKey 虚拟信用卡,并充值消费 如何拥有一个可长期在国内使用的国外手机号码 分享开通 ChatGPT Plus 过程 如何开通 Depay 虚拟信用卡,并充值消费 如何开通欧易Web3钱包, 交易入账 如何5分钟内1块钱注册 ChatGPT 如何注册美区的 Apple ID (2023年/无需科学上网) NAS折腾记(11): NASTool3.0体验和降级 NAS折腾记(10): Docker版本的NASTool配置 NAS折腾记(9): NASTool与微信交互,微信发送消息远程下载电影【多图】 NAS折腾记(8):群晖安装 NASTool 实现影音半自动化【多图】 内网穿透(2):Tailscale 组网实现内网穿透,操作简单,无成本 内网穿透(1):总结了11中内网穿透的方式,总有一种适合你 NAS折腾记(7):从零开始设置(黑)群晖系统 NAS折腾记(6):黑群晖系统安装好后怎么洗白? NAS折腾记(5):群晖硬盘休眠设置与分析 NAS折腾记(4): 20分钟手把手带你完美安装 DS918+ 黑群晖7.1.1 NAS折腾记(3):NAS 装机 NAS折腾记(2):B360-ITX 双M.2 双2.5G网口 6 SATA主版 开箱 NAS折腾记(1):328元的4盘位Nas机箱开箱 Openwrt + Clash 全局科学上网 Newifi3 刷入 OpenWrt 固件 v21.02 利用 Markdown 画一些流程图、时序图、甘特图等 Homelab(8): 搭建自用 Gitlab 与 Docker 仓库 Nginx Tcp 转发保留客户端真实 IP (PROXY Protocol) Homelab (7):IPSec VPN(基于证书认证)客户端设置 Homelab (6): 基于自签发证书的 IPSec VPN 搭建 Homelab (5): DDNS 动态域名解析 Homelab (4): Linux 服务器基础环境准备 Homelab (3): 整体网络与基础硬件介绍 Github Actions 初体验之自动化部署 Hexo 博客 记一次 Nginx DNS 缓存导致转发问题 Homelab (2): 电信悦me网关修改桥接模式,路由器拨号 Homelab (1):5分钟上手黑群晖 NAS 终极 Bash 脚本指南 Typora 自动上传图片到七牛云 Ubuntu 20.04 LTS 有线网卡驱动安装 折腾 Ubuntu 20.04 LTS 开发环境 Go学习笔记(九) 计时器的生命周期[译] 利用 git hook 规范你的代码与 commit message 规范 git commit message 与自动化版本控制 超详细 vim 配置 (with MacVim) Golang 中的 RESTful API 最佳实践 折腾服务器(开篇) 我的第一台个人服务器 Newifi3 实现低成本家庭级科学上网 Go学习笔记(八) | 使用 os/exec 执行命令 如何用 Go 调用 Windows API Mac OS 自动根据 WI-FI 名字改变网络位置 关于 Docker 清理 MIME Types 速查表 Go学习笔记(七) | 理解OAuth 2.0并实现一个客户端 我又又又把博客迁移了 Go学习笔记(六) | 使用swaggo自动生成Restful API文档 Go学习笔记(五) | 使用代码片段(snippets)提高编码效率 书单 - 2018 IPFS 初体验,利用 IPFS 托管你的静态网站 记一次 PostgreSQL LIKE 索引优化,联合字段 LIKE 查询优化。 Disqus 添加有趣的 Reactions 的功能 TLS 1.3 详解 (RFC 8446解读) gRPC在Go中的使用(三)gRPC实现TLS加密通信与流模式 gRPC在Go中的使用(二)gRPC实现简单通讯 gRPC在Go中的使用(一)Protocol Buffers语法与相关使用 CentOS 安装 tshark 抓包工具 Go学习笔记(四) | win上使用VSCode搭建Go开发环境 日常 Postgres 数据库点滴记录 简单了解 PKCS 规范 美食篇 | DIY戚风蛋糕(烤箱做蛋糕) Go学习笔记(三) | 怎么写Go基准测试(性能测试) TLS1.3正式更新,为Nginx添加TLS1.3的支持 一次诡异的数据库删除 GitHub Pages自定义域名开启HTTPS 证书透明度是什么?它是怎么工作的? Go学习笔记(二) | 我对 recover 的一点误解 搭建证书透明度(certificate-transparency)日志服务之从入门到放弃 修复远程登陆 Centos 时,出现 UTF-8 Warning HTTPS篇之SSL握手过程详解 Go学习笔记(一) | postgres与golang点点滴滴 AWS 命令行界面(aws-cli)从安装到快速上手 数字证书分类及怎么区分各类数字证书 常用 linux 命令小结(一)文件目录操作 云服务器搭建 hexo 博客,git hooks自动更新 SSH 免密登陆, SSH Config 配置 Golang CGO Mac 交叉编译 Windows 使用 goose 让数据库迁移更加轻松 开始使用Ghost
Go学习笔记(十)老项目迁移 go module 大型灾难记录
2021-07-20 · via Razeen`s Blog

最近在改造一个比较早期的一个项目,其中就涉及到用将原来 Vendor 管理依赖换成 Go Modules 来管理。 然而过程真是一波三折,在这里总结一下此次 Go Modules 改造中遇到的问题,以及解决方法。

背景

  • go version:

    $ go version
    go version go1.16.5 darwin/amd64
    
  • 简化的 demo 如下, 很 “简单” 我们只要把 hello world 输出即可。

    package main
    
    import (
    	"github.com/coreos/etcd/pkg/transport"
    	"github.com/google/certificate-transparency-go/tls"
    	"github.com/qiniu/api.v7/auth/qbox"
    	"go.etcd.io/etcd/clientv3"
    	"google.golang.org/grpc"
    	"qiniupkg.com/x/log.v7"
    )
    
    func main() {
    
    	_ = transport.TLSInfo{}
    
    	_ = clientv3.WatchResponse{}
    
    	_, _ = clientv3.New(clientv3.Config{})
    
    	_ = qbox.NewMac("", "")
    
    	_ = tls.DigitallySigned{}
    
    	_ = grpc.ClientConn{}
    
    	log.Info("hello world")
    }
    

实战

直接初始化,并 tidy 一下。

$ go mod init demo-go/gomod
go: creating new go.mod: module demo-go/gomod
go: to add module requirements and sums:
        go mod tidy
   
$ go mod tidy
go: finding module for ...
demo-go/gomod imports
        qiniupkg.com/x/log.v7: module qiniupkg.com/x@latest found (v1.11.5), but does not contain package qiniupkg.com/x/log.v7
demo-go/gomod imports
        github.com/qiniu/api.v7/auth/qbox imports
        github.com/qiniu/x/bytes.v7/seekable: module github.com/qiniu/x@latest found (v1.11.5), but does not contain package github.com/qiniu/x/bytes.v7/seekable
demo-go/gomod imports
        go.etcd.io/etcd/clientv3 imports
        github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context: package github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context provided by github.com/coreos/etcd at latest version v2.3.8+incompatible but not at required version v3.3.10+incompatible
demo-go/gomod imports
        go.etcd.io/etcd/clientv3 imports
        github.com/coreos/etcd/Godeps/_workspace/src/google.golang.org/grpc: package github.com/coreos/etcd/Godeps/_workspace/src/google.golang.org/grpc provided by github.com/coreos/etcd at latest version v2.3.8+incompatible but not at required version v3.3.10+incompatible
demo-go/gomod imports
        go.etcd.io/etcd/clientv3 imports
        github.com/coreos/etcd/Godeps/_workspace/src/google.golang.org/grpc/credentials: package github.com/coreos/etcd/Godeps/_workspace/src/google.golang.org/grpc/credentials provided by github.com/coreos/etcd at latest version v2.3.8+incompatible but not at required version v3.3.10+incompatible
demo-go/gomod imports
        go.etcd.io/etcd/clientv3 imports
        github.com/coreos/etcd/storage/storagepb: package github.com/coreos/etcd/storage/storagepb provided by github.com/coreos/etcd at latest version v2.3.8+incompatible but not at required version v3.3.10+incompatible

好家伙,报错了。我们先看到前两行

  1. qiniupkg.com/x@latest 中没有 qiniupkg.com/x/log.v7
  2. github.com/qiniu/x@latest 中没有 github.com/qiniu/x/bytes.v7/seekable

这看起来应该是一个问题, qiniupkg.com/xgithub.com/qiniu/x 应该是同一个包,不同镜像。于是我到 Github 看一下 @lastet 版本的代码,确实没有bytes.v7 包了。人肉查找,最后在 v1.7.8 版本,我们找到了 bytes.v7 包。

于是,我们可以指定一下版本。

go mod edit -replace qiniupkg.com/x=qiniupkg.com/x@v1.7.8
go mod edit -replace github.com/qiniu/x=github.com/qiniu/x@v1.7.8

继续往下看,接下来的几个问题是一类的,都是etcd导致的。

意思是 go.etcd.io/etcd/clientv3 导入了 github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context, 同时 github.com/coreos/etcd@v2.3.8 中 提供了 github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context 。 但是,我们这里需要 github.com/coreos/etcd@v3.3.10, 而该版本并不提供 github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context

我们直接更新 etcd 到的 v3.3.10 试试。

go mod edit -replace go.etcd.io/etcd=go.etcd.io/etcd@v3.3.20+incompatible

我们再 go mod tidy 下。

$ go mod tidy
go: demo-go/gomod imports
        go.etcd.io/etcd/clientv3 tested by
        go.etcd.io/etcd/clientv3.test imports
        github.com/coreos/etcd/auth imports
        github.com/coreos/etcd/mvcc/backend imports
        github.com/coreos/bbolt: github.com/coreos/bbolt@v1.3.6: parsing go.mod:
        module declares its path as: go.etcd.io/bbolt
                but was required as: github.com/coreos/bbolt

这个错误和鸟窝这篇 Etcd使用go module的灾难一致,go.etcd.io/bboltgithub.com/coreos/bbolt 包名不一致,我们替换一下。

go mod edit -replace github.com/coreos/bbolt@v1.3.6=go.etcd.io/bbolt@v1.3.6

继续,go mod tidy 一下。

$ go mod tidy
...
demo-go/gomod imports
        go.etcd.io/etcd/clientv3 imports
        github.com/coreos/etcd/clientv3/balancer: module github.com/coreos/etcd@latest found (v2.3.8+incompatible), but does not contain package github.com/coreos/etcd/clientv3/balancer
demo-go/gomod imports
        go.etcd.io/etcd/clientv3 imports
        github.com/coreos/etcd/clientv3/balancer/picker: module github.com/coreos/etcd@latest found (v2.3.8+incompatible), but does not contain package github.com/coreos/etcd/clientv3/balancer/picker
demo-go/gomod imports
        go.etcd.io/etcd/clientv3 imports
        github.com/coreos/etcd/clientv3/balancer/resolver/endpoint: module github.com/coreos/etcd@latest found (v2.3.8+incompatible), but does not contain package github.com/coreos/etcd/clientv3/balancer/resolver/endpoint
demo-go/gomod imports
        go.etcd.io/etcd/clientv3 imports
        github.com/coreos/etcd/clientv3/credentials: module github.com/coreos/etcd@latest found (v2.3.8+incompatible), but does not contain package github.com/coreos/etcd/clientv3/credentials
demo-go/gomod imports
        go.etcd.io/etcd/clientv3 tested by
        go.etcd.io/etcd/clientv3.test imports
        github.com/coreos/etcd/integration imports
        github.com/coreos/etcd/proxy/grpcproxy imports
        google.golang.org/grpc/naming: module google.golang.org/grpc@latest found (v1.39.0), but does not contain package google.golang.org/grpc/naming

好家伙,又是etcd。 仔细一看,我们导入了github.com/coreos/etcdgo.etcd.io/etcd 两个版本etcd, 我们前面只替换了一个。现在我们把另外一个也替换了。

go mod edit -replace github.com/coreos/etcd=github.com/coreos/etcd@v3.3.20+incompatible

go mod tidy下,这个错误没有了,但还有个grpc的错误,继续找原因。原来是 google.golang.org/grpc v1.39.0 版本没有 google.golang.org/grpc/naming 包。 上 Github 仓库, 找了一下历史版本,v1.29.1上是有这个包的,我们继续替换。

go mod edit -replace google.golang.org/grpc=google.golang.org/grpc@v1.29.1

这下,终于,go mod tidy通过了,可以开心的输出hello world 了。

然而,

$ go run main.go
# github.com/coreos/etcd/clientv3/balancer/resolver/endpoint
../../../go/pkg/mod/github.com/coreos/etcd@v3.3.20+incompatible/clientv3/balancer/resolver/endpoint/endpoint.go:114:78: undefined: resolver.BuildOption
../../../go/pkg/mod/github.com/coreos/etcd@v3.3.20+incompatible/clientv3/balancer/resolver/endpoint/endpoint.go:182:31: undefined: resolver.ResolveNowOption
# github.com/coreos/etcd/clientv3/balancer/picker
../../../go/pkg/mod/github.com/coreos/etcd@v3.3.20+incompatible/clientv3/balancer/picker/err.go:37:44: undefined: balancer.PickOptions
../../../go/pkg/mod/github.com/coreos/etcd@v3.3.20+incompatible/clientv3/balancer/picker/roundrobin_balanced.go:55:54: undefined: balancer.PickOptions

意不意外,惊不惊喜!!

原来etcd包依赖了grpcresolver包,但我导入的v1.29.1版本的grpc是没有这个包的。到 grpc仓库 挨个版本看了一下,确实只有v1.26.0版本才声明了type BuildOption 。于是,我们再次使用替换大法。

go mod edit -replace google.golang.org/grpc=google.golang.org/grpc@v1.26.0

再次tidy, 运行! 终于,看到了久违的hello world!

$ go run main.go
2021/07/20 12:27:09.642431 [INFO] /Users/razeen/wspace/github/demo-go/gomod/main.go:26: hello world

总结

项目规范

现在我们回过头看下这个 demo 项目,其实很有问题。

	"github.com/coreos/etcd/pkg/transport"
	"github.com/google/certificate-transparency-go/tls"
	"github.com/qiniu/api.v7/auth/qbox"
	"go.etcd.io/etcd/clientv3"
	"google.golang.org/grpc"
	"qiniupkg.com/x/log.v7"

etcdqiniupkg的包完全可以统一,只导入一种!而且,后来我们发现log.v7这包也是意外导入的….

这也是在改造我们一些老的项目时遇到的问题,以前用vendor go get 没有注意到这些问题,这是需要提前规范的。

看懂 go.mod

我们来简单看一下,经历各种坎坷后,得出的go.mod 文件。

module demo-go/gomod

go 1.16

replace qiniupkg.com/x => qiniupkg.com/x v1.7.8

replace github.com/qiniu/x => github.com/qiniu/x v1.7.8

replace go.etcd.io/etcd => go.etcd.io/etcd v3.3.20+incompatible

replace github.com/coreos/bbolt v1.3.6 => go.etcd.io/bbolt v1.3.6

replace github.com/coreos/etcd => github.com/coreos/etcd v3.3.20+incompatible

replace google.golang.org/grpc => google.golang.org/grpc v1.26.0

require (
	github.com/coreos/bbolt v1.3.6 // indirect
	github.com/coreos/etcd v3.3.10+incompatible
	github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
	github.com/google/certificate-transparency-go v1.1.1
	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
	github.com/qiniu/api.v7 v7.2.5+incompatible
	github.com/qiniu/x v0.0.0-00010101000000-000000000000 // indirect
	github.com/soheilhy/cmux v0.1.5 // indirect
	github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
	go.etcd.io/etcd v0.0.0-20200513171258-e048e166ab9c
	google.golang.org/grpc v1.29.1
	qiniupkg.com/x v0.0.0-00010101000000-000000000000
	sigs.k8s.io/yaml v1.2.0 // indirect
)

我们先看一个常见的这几个指令

  • module 定义主模块的路径;
  • go 编写该mod文件时的go版本;
  • require 声明给定模块依赖项的最低要求版本;
  • replace 手动指定的依赖模块 (可以替换全部的版本、指定的版本、本地的版本等等 );

还有就是 v3.3.20+incompatible 后面的 +incompatible , 这是指兼容的版本,指依赖库的版本是v2 或以上,但go.mod和 依赖库路径 没有按照官方指定的方式命名,会加上这个。

v0.0.0-00010101000000-000000000000 这是一个伪版本,在和 不兼容 module 或 标记的版本不可用的时候,回打上这个伪版本。

// indirect 这指明这些不是我们直接引用的依赖。

除此之外,以下指令也可了解一下。

# 查看当前模块以及所有的依赖模块
go list -m all

# 查看某个模块的以及打标签的版本
go list -m -versions go.etcd.io/etcd

# 升级特定的包
go get xx@version 升级特定的包

# 了解为什么需要模块
go mod why -m all  

# 为什么需要指定(google.golang.org/grpc)的模块
go mod why -m google.golang.org/grpc

更多可以细读官方文档,感谢阅读。

参考