go/golang 新版 Protobuf API尝鲜

l7l1l0l · 2020-03-08 22:17:08 · 2536 次点击 · 预计阅读时间 5 分钟 · 大约8小时之前 开始浏览    
这是一个创建于 2020-03-08 22:17:08 的文章,其中的信息可能已经有所发展或是发生改变。

简介

Protobuf从v2用到了v3,从C++用到了Golang,个人特别喜欢。3月2日,Go官宣,有了新版的API。中文介绍 说实话,没有太看明白。的确有点尴尬,从14年用到了20年,不过想那么多干嘛。用就完了。

因为V2 API所涉及的新功能,目前我均未使用到,本文并未介绍

开始尝试

先来个小demo

相关proto文件就不展示了
请注意引用新版API,不是github,而是google.golang.org
强烈建议大家开始使用go module,极度舒适,妈妈再也不担心我拉不到代码了!!!

package serverproto

import (
    "google.golang.org/protobuf/proto"
    "testing"
)

func TestBGFHead_GetUserId(t *testing.T) {
    head := &BGFHead{}
    head.UserId = 30020

    proto.Marshal(head)
}

go test走起,然而竟然报错啦

[luojie@localhost serverproto]$ go test
# go/protobuf/serverproto [go/protobuf/serverproto.test]
./server_test.go:12:15: cannot use head (type *BGFHead) as type protoreflect.ProtoMessage in argument to "google.golang.org/protobuf/proto".Marshal:
    *BGFHead does not implement protoreflect.ProtoMessage (missing ProtoReflect method)
FAIL    go/protobuf/serverproto [build failed]

解决问题

因为是新版V2 API并不向前兼容V1的API,所以此处需要更新protoc-gen-go 说明文档

go install google.golang.org/protobuf/cmd/protoc-gen-go

使用了go module之后,install的速度也是快到飞起 !!!重新生成代码 再次go test

[luojie@localhost serverproto]$ go test
PASS
ok      go/protobuf/serverproto    0.003s

分析

V1的go代码

type BGFHead struct {
    UserId               int32       `protobuf:"varint,1,opt,name=userId,proto3" json:"userId,omitempty"`
    Cmd                  uint32      `protobuf:"varint,2,opt,name=cmd,proto3" json:"cmd,omitempty"`
    TransTypes           TransType   `protobuf:"varint,3,opt,name=transTypes,proto3,enum=serverproto.TransType" json:"transTypes,omitempty"`
    MsgType              uint32      `protobuf:"varint,4,opt,name=msgType,proto3" json:"msgType,omitempty"`
    SSerId               int32       `protobuf:"varint,5,opt,name=sSerId,proto3" json:"sSerId,omitempty"`
    SSerType             ServerType  `protobuf:"varint,6,opt,name=sSerType,proto3,enum=serverproto.ServerType" json:"sSerType,omitempty"`
    DSerId               int32       `protobuf:"varint,7,opt,name=dSerId,proto3" json:"dSerId,omitempty"`
    DSerType             ServerType  `protobuf:"varint,8,opt,name=dSerType,proto3,enum=serverproto.ServerType" json:"dSerType,omitempty"`
    Cooks                []*CookInfo `protobuf:"bytes,9,rep,name=Cooks,proto3" json:"Cooks,omitempty"`
    GroupId              []int64     `protobuf:"varint,10,rep,packed,name=groupId,proto3" json:"groupId,omitempty"`
    XXX_NoUnkeyedLiteral struct{}    `json:"-"`
    XXX_unrecognized     []byte      `json:"-"`
    XXX_sizecache        int32       `json:"-"`
}
}

V2的go代码

type BGFHead struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields

    UserId     int32       `protobuf:"varint,1,opt,name=userId,proto3" json:"userId,omitempty"`                                    //用户id
    Cmd        uint32      `protobuf:"varint,2,opt,name=cmd,proto3" json:"cmd,omitempty"`                                          //命令字
    TransTypes TransType   `protobuf:"varint,3,opt,name=transTypes,proto3,enum=serverproto.TransType" json:"transTypes,omitempty"` //发送类型
    MsgType    uint32      `protobuf:"varint,4,opt,name=msgType,proto3" json:"msgType,omitempty"`                                  //消息类型
    SSerId     int32       `protobuf:"varint,5,opt,name=sSerId,proto3" json:"sSerId,omitempty"`                                    //源服务 id
    SSerType   ServerType  `protobuf:"varint,6,opt,name=sSerType,proto3,enum=serverproto.ServerType" json:"sSerType,omitempty"`    //源服务 type
    DSerId     int32       `protobuf:"varint,7,opt,name=dSerId,proto3" json:"dSerId,omitempty"`                                    //目标服务 id
    DSerType   ServerType  `protobuf:"varint,8,opt,name=dSerType,proto3,enum=serverproto.ServerType" json:"dSerType,omitempty"`    //目标服务 type
    Cooks      []*CookInfo `protobuf:"bytes,9,rep,name=Cooks,proto3" json:"Cooks,omitempty"`                                       //我也不知道是干啥的
    GroupId    []int64     `protobuf:"varint,10,rep,packed,name=groupId,proto3" json:"groupId,omitempty"`                          //组id 与trans_types有关联
}

结论

  • V2生成的go代码含有proto文件中的注释,个人非常喜欢,V1版本go代码不包含注释,复杂或者嵌套层次比较高的时候,没有注释,真是另人抓狂;
  • 在官宣说明中有提到旧版无意义的字段也没有了;
  • V2代码中新增了statesizeCacheunknownFields三个字段,具体意义有待研究;
  • V2中多引入两个包,分别为protoreflectprotoimpl

应用

若现有项目还在用V1的API,新项目想使用V2的API的简单的方法

步骤

  • 修改当前的protoc-gen-go为protoc-gen-goV1;
  • 安装V2版本的protoc-gen-go;
  • 将protoc-gen-go修改为protoc-gen-goV2;
  • 将protoc-gen-goV1修改为protoc-gen-go;

Windows下同理

使用

V1版本

和原来一样,没有任何改变

V2版本

protoc --goV2_out=:. recharge.proto

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2536 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传