Protobuf 中 any 的妙用


 

在使用 GRPC 时,常规的操作是将 message 定义好后进行数据传输,但总会遇到某些数据结构进行组合的操作,采用默认的定义 message 方式,造成代码量的激增。为了解决这个问题 protobuf 提供类型 any 解决 GRPC 中泛型的处理方式

目录结构

. ├── main.go └── rpc ├── rsp.pb.go └── rsp.proto 
  • 1
  • 2
  • 3
  • 4
  • 5

首先,我们定义我们需要传输的消息

path project_dir/rpc/rsp.proto
采用 proto3 协议
定义 TestAny 用于测试 any 的动态传输
定义 Response 作为 GRPC 通用的消息交互

rsp.proto 内容

syntax = "proto3";

package rpc;

option go_package = ".;rpc";

import "google/protobuf/any.proto";

message TestAny {
  uint64 Id = 1;
  string Title = 2;
  string Content = 3;
}

message Response {
  uint32 Code = 1;
  string Msg = 2;
  google.protobuf.Any data = 3;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

使用 protoc 编译工具,编译 rsp.proto,生成 rsp.pb.go 文件

path project_dir/rpc/rsp.pb.go
我们并不需要关注 rsp.pb.go 内部的所有内容
仅需要关注生成的消息体

> protoc --go_out=./ rsp.proto
  • 1

rsp.pb.go 内容

通过 protoc 工具,生成了两个 struct,及为我们定义在 proto 文件中的 message

type TestAny struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Id uint64 `protobuf:"varint,1,opt,name=Id,proto3" json:"Id,omitempty"` Title string `protobuf:"bytes,2,opt,name=Title,proto3" json:"Title,omitempty"` Content string `protobuf:"bytes,3,opt,name=Content,proto3" json:"Content,omitempty"` } type Response struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Code uint32 `protobuf:"varint,1,opt,name=Code,proto3" json:"Code,omitempty"` Msg string `protobuf:"bytes,2,opt,name=Msg,proto3" json:"Msg,omitempty"` Data *any.Any `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

测试使用 any

下面我们将演示实际场景中的应用
通过 ptypes.MarshalAny(marshal) 将我们定义的消息进行编码
通过 ptypes.UnmarshalAny(any, unmarshal) 对已经编码的消息进行反编码

main.go 内容

func main() { marshal := &rpc.TestAny{ Id: 1, Title: "标题", Content: "内容", } any, err := ptypes.MarshalAny(marshal) fmt.Println(any, err) // [type.googleapis.com/rpc.TestAny]:{Id:1 Title:"标题" Content:"内容"} <nil> msg := &rpc.Response{ Code: 0, Msg: "success", Data: any, } fmt.Println(msg) // Msg:"success" data:{[type.googleapis.com/rpc.TestAny]:{Id:1 Title:"标题" Content:"内容"}} unmarshal := &rpc.TestAny{} err = ptypes.UnmarshalAny(msg.Data, unmarshal) fmt.Println(unmarshal, err) // Id:1 Title:"标题" Content:"内容" <nil> }


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM