將 protobuf 訊息解組到介面{}以促進型別轉換是不可行的,因為 proto.Unmarshal函數需要一個類型的參數proto.Message,具體protobuf類型的介面
如果至少有一些上下文資訊(例如字串或數字)伴隨字節切片,您可以使用該資訊來映射到預期的protobuf 類型並在將其傳遞給proto.Unmarshal先前實例化它:
func decodeWithMetadata(data []byte, identifier string) error { var message proto.Message switch identifier { case "foo": message = &mypb.Foo{} case "bar": message = &mypb.Bar{} } if err := proto.Unmarshal(data, message); err != nil { return err } log.Printf("%v\n", data) return nil }
但是,如果位元組有效負載完全未知,請考慮protowire 包,它允許從有線格式的protobuf 訊息中提取有限的資訊。請記住,protobuf 訊息的線路表示不明確,導致語意較弱。
以下程式碼解析未知的 protobuf 訊息:
type Field struct { Tag Tag Val Val } type Tag struct { Num int32 Type protowire.Type } type Val struct { Payload interface{} Length int } func parseUnknown(b []byte) []Field { // ... implementation to parse unknown protobuf messages as described in the provided answer ... }
給定一個 protobuf模式像:
message Foo { string a = 1; string b = 2; Bar bar = 3; } message Bar { string c = 1; }
以下程式碼示範如何使用解析器:
// Parse the protobuf message as byte slice b := []byte{0x0a, 0x01, 0x41, 0x12, 0x01, 0x42, 0x1a, 0x03, 0x43} fields := parseUnknown(b) for _, field := range fields { fmt.Printf("%#v\n", field) }
輸出:
main.Field{Tag:main.Tag{Num:1, Type:2}, Val:main.Val{Payload:[]uint8{0x41}, Length:1}} main.Field{Tag:main.Tag{Num:2, Type:2}, Val:main.Val{Payload:[]uint8{0x42}, Length:1}} main.Field{Tag:main.Tag{Num:1, Type:2}, Val:main.Val{Payload:[]uint8{0x43}, Length:1}} main.Field{Tag:main.Tag{Num:3, Type:2}, Val:main.Val{Payload:[]main.Field{main.Field{Tag:main.Tag{Num:1, Type:2}, Val:main.Val{Payload:[]uint8{0x43}, Length:1}}}, Length:3}}
以上是如何在 Go 中解組未知的 Protobuf 訊息?的詳細內容。更多資訊請關注PHP中文網其他相關文章!