找回密码
 立即注册
查看: 294|回复: 2

记一次奇妙的go-protobuf包升级之旅

[复制链接]
发表于 2021-11-25 15:18 | 显示全部楼层 |阅读模式
今天聊一个最近升级go的protobuf的故事。过程很是奇妙(曲折)
前两天,一个项目的dependabot提示包github.com/golang/protobuf 可以从V1.3.5升级到V1.4.0
Round One

本以为直接升级就行,但是没过CI,是发现旧版(V1.3.5)测试代码用了pb生成代码的XXX_Size()方法计算消息大小
在新版(v1.4.0)里panic了
我们来看下他们有啥不同:
为简化,我们proto文件用官方的helloworld.proto
通过以下方式生成V1.3.5版本的pb文件
curl -O https://raw.githubusercontent.com/grpc/grpc-go/master/examples/helloworld/helloworld/helloworld.proto
brew install protobuf
GO111MODULE=on go get -u github.com/golang/protobuf/protoc-gen-go@v1.3.5
protoc  --go_out=plugins=grpc:. helloworld.proto再替换github.com/golang/protobuf/protoc-gen-go@v1.4.0,生成新版pb文件
查找XXX_Size函数
旧版中没问题
// helloword.pb.go
func (m *HelloRequest) XXX_Size() int {
  return xxx_messageInfo_HelloRequest.Size(m)
}
var xxx_messageInfo_HelloRequest proto.InternalMessageInfo

// github.com/golang/protobuf@v1.3.5/proto/table_marshal.go
func (a *InternalMessageInfo) Size(msg Message) int {
新版pb文件中没有了InternalMessageInfo类型
但源码中能找到,是被废弃了。
// github.com/golang/protobuf@v1.4.0/proto/deprecated.go
// Deprecated: Do not use.
type InternalMessageInfo struct{}

func (*InternalMessageInfo) Size(Message) int { panic("not implemented") }
// 同样废弃的还有: DiscardUnknown, Marshal, Merge, Unmarshal
那新版代码中怎么获取大小?
查看源码中例子,proto.Size(m Message) int可以实现
InternalMessageInfo也变成了接口type Message = protoiface.MessageV1
这个InternalMessageInfo的废弃在版本升级中也提到了,详见generated-code
好,替换方法,第一回合结束



Round Two

等等,再仔细看了下github.com/golang/protobuf文档,里边提到v1.4.0版本后, 后边代码将交由google.golang.org/protobuf Repo维护,看来谷歌要把pb的包都收到自己组织下
那我顺手直接把grpc生成工具也替换过去呗!
GO111MODULE=on go get -u google.golang.org/protobuf/cmd/protoc-gen-go@v1.21.0
再次生成代码
新工具自动提示要求proto文件中增加:
option go_package = ".;helloworld";
居然失败了。。。提示:
--go_out: protoc-gen-go: plugins are not supported; use 'protoc --go-grpc_out=...' to generate gRPC难道是新增了flag,尝试:
protoc  --go-grpc_out=. helloworld.protoWhat? 失败+1。。。
protoc-gen-go-grpc: program not found or is not executable
Please specify a program using absolute path or make sure the program is available in your PATH system variable
--go-grpc_out: protoc-gen-go-grpc: Plugin failed with status code 1.



protoc-gen-go-grpc是新工具?
搜了下,确实有这个工具,说新版本会用他来生成grpc,主要是为了更好支持protobuf reflection
这里说一下:
proto文件中的service是需要grpc的plugin才能生成对应pb代码 所以旧版工具有参数--go_out=plugins=grpc:
尝试安装下:
GO111MODULE=on go get google.golang.org/protobuf/cmd/protoc-gen-go-grpc失败+2。。。
go get google.golang.org/protobuf/cmd/protoc-gen-go-grpc: module google.golang.org/protobuf@upgrade found (v1.21.0), but does not contain package google.golang.org/protobuf/cmd/protoc-gen-go-grpc



goDoc里有protoc-gen-go-grpc,Repo里没有,这是什么操作?
猜测这问题应该有人遇到吧,果然搜到了issue:plugins are not supported:grpc
原来是google.golang.org/protobuf先发布了,里边也包含了新版的protoc-gen-go,
只是其不再支持grpc生成,需要另一个工具protoc-gen-go-grpc
然而它还没有发布,还在Review中。。。(当然目前也不会是稳定版本)



不过,官方也说了,依然可以用旧包github.com/golang/protobuf的protoc-gen-go-grpc工具生成grpc代码
因为旧包protoc-gen-go-grpc里依然可以用新包protoc-gen-go-grpc里生成grpc代码的gengogrpc, 见comment
Round Three

好吧,那就只升级代码中调用的protobuf为google.golang.org/protobuf@v1.21.0,代码生成工具还用旧版里github.com/golang/protobuf/protoc-gen-go@v1.4.0吧
再次生成pb文件, 终于没有问题了, peace finally



proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
只是看着生成代码里的依然需要import的旧包github.com/golang/protobuf,总感觉哪里怪怪的
升级完了,却依赖了两种protobuf包。。。
最后,劝大家不着急就再等等再升级吧
(另外没事干升级到新包干什么!)
当然这次protobuf的breaking change还是很有意义的,不仅让将protobuf反射作为pb的一级功能,还提供了很多处理工具,详细看下: v1.21.0-release
<hr/>文章首发公众号:newbmiao
推荐阅读:Dig101-Go系列

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
发表于 2021-11-25 15:27 | 显示全部楼层
感谢,oneof这玩意太反人类了...
发表于 2021-11-25 15:33 | 显示全部楼层
protoc-gen-go-grpc通过"go install http://google.golang.org/grpc/cmd/protoc-gen-go-grpc"安装哦
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-6-4 22:36 , Processed in 0.105980 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表