• 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>
    }
  • 相关阅读:
    stl_heap
    关于随机数 C++
    关于if语句的细节
    C++关于智能指针
    sqlyog
    win10 64位 汇编环境
    Qt 乱码
    Vux使用经验
    Flex布局新旧混合写法详解
    【原】npm 常用命令详解
  • 原文地址:https://www.cnblogs.com/ExMan/p/13892736.html
Copyright © 2020-2023  润新知