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)
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 }
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"}}
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}}
Zusätzliche Überlegungen
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!