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

Wie kann ich unbekannte Protobuf-Nachrichten in Go entmarshalieren?

Barbara Streisand
Freigeben: 2024-11-30 09:21:13
Original
945 Leute haben es durchsucht

How Can I Unmarshal Unknown Protobuf Messages in Go?

Fallstricke beim Unmarshaling unbekannter Protobuf-Nachrichten

Die Unfähigkeit von proto.Unmarshal, mit Interface-{}-Typen umzugehen, ist ein wesentlicher Aspekt, den es zu verstehen gilt. Seine Methodensignatur schreibt die Übergabe eines proto.Message-Arguments vor, das durch konkrete Protobuffer-Typen implementiert wird.

Die Herausforderung meistern

Beim Umgang mit rohen Protobuffer-Nutzlasten, denen zusätzlicher Kontext fehlt ist es wichtig, dass neben dem Byte-Slice zumindest einige identifizierende Informationen (z. B. eine Zeichenfolge oder eine Zahl) vorhanden sind. Diese Informationen können verwendet werden, um die konkrete Nachricht dem spezifischen Protobuffer zuzuordnen. Sie können dann eine Switch-Anweisung verwenden, um den entsprechenden Typ zu instanziieren und an Unmarshal zu übergeben:

switch atLeastSomething {
    case "foo":
        message = &mypb.Foo{}
    case "bar":
        message = &mypb.Bar{}
}
_ = proto.Unmarshal(data, message)
Nach dem Login kopieren

Das Unvorhersehbare umarmen: Völlig unbekannte Nachrichten dekodieren

In seltenen Fällen , könnten Sie auf eine völlig unbekannte Protobuffer-Nutzlast stoßen. Das Protowire-Paket bietet eine Lösung, um einige Informationen daraus zu extrahieren, allerdings mit inhärenten Einschränkungen. Der Inhalt der Nutzlast kann abgerufen werden, allerdings mit schwächerer Semantik.

Implementierungsdetails

Hier ist ein vereinfachter Parser für unbekannte Proto-Nachrichten:

func parseUnknown(b []byte) []Field {
    // Data model
    type Field struct {
        Tag Tag
        Val Val
    }
    type Tag struct {
        Num int32
        Type protowire.Type
    }
    type Val struct {
        Payload interface{}
        Length  int
    }
    // Parsing algorithm
    fields := make([]Field, 0)
    for len(b) > 0 {
        n, t, fieldlen := protowire.ConsumeField(b)
        if fieldlen < 1 {
            return nil
        }
        ... // Parsing logic
        fields = append(fields, field)
        b = b[fieldlen:]
    }
    return fields
}
Nach dem Login kopieren

Beispieleingabe und -ausgabe

Mit dem Beispiel Eingabe:

message Foo {
  string a = 1;
  string b = 2;
  Bar bar = 3;
}
message Bar {
  string c = 1;
}
&test.Foo{A: "A", B: "B", Bar: &test.Bar{C: "C"}}
Nach dem Login kopieren

Die Ausgabe lautet:

Field{Tag:Tag{Num:1, Type:2}, Val:Val{Payload:[]uint8{0x41}, Length:1}}
Field{Tag:Tag{Num:2, Type:2}, Val:Val{Payload:[]uint8{0x42}, Length:1}}
Field{Tag:Tag{Num:1, Type:2}, Val:Val{Payload:[]uint8{0x43}, Length:1}}
Field{Tag:Tag{Num:3, Type:2}, Val:Val{Payload:[]Field{Field{Tag:Tag{Num:1, Type:2}, Val:Val{Payload:[]uint8{0x43}, Length:1}}}, Length:3}}
Nach dem Login kopieren

Zusätzliche Überlegungen

  • Unternachrichten werden rekursiv analysiert und gespeichert , falls gültig. Andernfalls werden Bytes unverändert gespeichert.
  • Wiederholte Felder werden nicht explizit behandelt, können aber aus wiederholten Tag.Num-Werten nach dem Parsen abgeleitet werden.
  • Es wird erwartet, dass Karten semantisch äquivalent zu sind wiederholte Schlüssel/Wert-Paare.
  • Eine der Informationen geht wahrscheinlich verloren, sodass nur die Menge erhalten bleibt Wert.

Alternative: Any und Interface{}

Während Any zunächst wie eine geeignete Option für unbekannte Nachrichten erscheinen mag, hat es eine streng definierte Struktur und kann nicht zur Dekodierung unbekannter Nutzlasten verwendet werden. Darüber hinaus ist Protowire aufgrund seiner spezifischen Struktur nicht auf Any anwendbar.

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

Quelle:php.cn
Erklärung dieser Website
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
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage