在使用 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> }