型キャストを容易にするために protobuf メッセージをインターフェースにアンマーシャリングする{}は、proto.Unmarshal 関数が type の引数を期待しているため、実現できません。 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 }
ただし、バイト ペイロードが完全に不明な場合は、ワイヤー フォーマットの protobuf メッセージから限られた情報を抽出できる protowire パッケージを検討してください。 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 スキーマlike:
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 中国語 Web サイトの他の関連記事を参照してください。