Heim >Backend-Entwicklung >Golang >Wie entmarshaliere ich unbekannte Protobuf-Nachrichten in Go?

Wie entmarshaliere ich unbekannte Protobuf-Nachrichten in Go?

Linda Hamilton
Linda HamiltonOriginal
2024-12-03 02:15:10756Durchsuche

How to Unmarshal Unknown Protobuf Messages in Go?

Unmarshalling unbekannter Protobuf-Nachrichten in Go

Unmarshalling von Protobuf-Nachrichten in einer Schnittstelle{} zur Erleichterung der Typumwandlung ist nicht möglich, da die Funktion proto.Unmarshal ein Argument vom Typ erwartet proto.Message, eine Schnittstelle, die konkrete Protobuf-Typen implementieren.

Alternativer Ansatz mit bekannten Metadaten

In Fällen, in denen dem Byte-Slice zumindest einige Kontextinformationen (z. B. eine Zeichenfolge oder eine Zahl) beiliegen, können Sie diese Informationen verwenden, um sie dem erwarteten Protobuf-Typ zuzuordnen und ihn zu instanziieren, bevor Sie ihn an Proto übergeben .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
}

Völlig unbekannte Nutzlasten analysieren

Allerdings, wenn Die Byte-Nutzlast ist völlig unbekannt. Betrachten Sie das Protowire-Paket, das das Extrahieren begrenzter Informationen aus Wire-formatierten Protobuf-Nachrichten ermöglicht. Beachten Sie, dass die Drahtdarstellung von Protobuf-Nachrichten mehrdeutig ist, was zu einer schwachen Semantik führt.

Parser-Implementierung

Der folgende Code analysiert unbekannte Protobuf-Nachrichten:

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 ...
}

Beispiel Verwendung

Angesichts eines Protobuf-Schemas wie:

message Foo {
  string a = 1;
  string b = 2;
  Bar bar = 3;
}

message Bar {
  string c = 1;
}

Der folgende Code zeigt, wie der Parser verwendet wird:

// 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)
}

Ausgabe:

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}}

Das obige ist der detaillierte Inhalt vonWie entmarshaliere ich unbekannte Protobuf-Nachrichten in Go?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn