Maison >développement back-end >Golang >Comment désorganiser les messages Protobuf inconnus dans Go ?
Désassembler les messages protobuf dans une interface{} pour faciliter la conversion de type n'est pas réalisable car la fonction proto.Unmarshal attend un argument de type proto.Message, une interface implémentée par des types protobuf concrets.
Dans les cas où au moins certaines informations contextuelles (par exemple, une chaîne ou un nombre) accompagnent la tranche d'octets, vous pouvez utiliser ces informations pour mapper le type de protobuf attendu et l'instancier avant de le transmettre à 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 }
Cependant, si la charge utile de l'octet est entièrement inconnue, considérez le package protowire, qui permet d'extraire des informations limitées à partir de messages protobuf au format filaire. Gardez à l'esprit que la représentation filaire des messages protobuf est ambiguë, ce qui conduit à une sémantique faible.
Le code suivant analyse les messages protobuf inconnus :
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 ... }
Étant donné un schéma protobuf comme :
message Foo { string a = 1; string b = 2; Bar bar = 3; } message Bar { string c = 1; }
Le code suivant montre comment utiliser l'analyseur :
// 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) }
Sortie :
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}}
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!