ホームページ > バックエンド開発 > Golang > Go で不明な Protobuf メッセージをアンマーシャリングする方法

Go で不明な Protobuf メッセージをアンマーシャリングする方法

Linda Hamilton
リリース: 2024-12-03 02:15:10
オリジナル
728 人が閲覧しました

How to Unmarshal Unknown Protobuf Messages in Go?

Go での不明な Protobuf メッセージのアンマーシャリング

型キャストを容易にするために 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
}
ログイン後にコピー

Parsing に渡す前にインスタンス化します。完全に不明なペイロード

ただし、バイト ペイロードが完全に不明な場合は、ワイヤー フォーマットの 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 サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート