protobuf ist wie folgt definiert:
syntax = "proto3" message hugemessage { // omitted } message request { string name = 1; hugemessage payload = 2; }
In einem Fall habe ich eine hugemessage
,我想用其他字段打包它,然后将该消息传输给其他人。因此,我必须将 hugemessage
二进制文件unmarshal放入go结构中,将其打包到request
中,然后再次marshal。由于 hugemessage
的 hgue 大小,unmarshal 和 marshal 的成本难以承受。那么我可以重用 hugemessage
-Binärdatei von jemandem erhalten, ohne die Protobuf-Definition zu ändern?
func main() { // receive it from file or network, not important. bins, _ := os.ReadFile("hugeMessage.dump") var message HugeMessage _ = proto.Unmarshal(bins, &message) // slow request := Request{ name: "xxxx", payload: message, } requestBinary, _ := proto.Marshal(&request) // slow // send it. os.WriteFile("request.dump", requestBinary, 0644) }
Die kurze Antwort lautet: Nein, es gibt keinen einfachen oder standardmäßigen Weg, dies zu erreichen.
Die naheliegendste Strategie besteht darin, es so zu machen, wie Sie es derzeit tun – Unmarshalieren hugemessage
,将其设置为 request
und dann erneut Marshallen. Die Golang-Protobuf-API-Oberfläche bietet nicht wirklich eine Möglichkeit, mehr zu tun – und das aus gutem Grund.
Trotzdem gibt es Möglichkeiten, das zu erreichen, was Sie tun möchten. Diese sind jedoch nicht unbedingt sicher oder zuverlässig, daher müssen Sie diese Kosten gegen das abwägen, was Sie jetzt haben.
Eine Möglichkeit, Unmarshalling zu vermeiden, besteht darin, die Art und Weise zu nutzen, wie Nachrichten normalerweise serialisiert werden
message request { string name = 1; hugemessage payload = 2; }
..entspricht
message request { string name = 1; bytes payload = 2; }
.. wobei payload
包含针对某些 hugemessage
调用 marshal(...)
das Ergebnis ist.
Wenn wir also die folgende Definition haben:
syntax = "proto3"; message hugemessage { bytes field1 = 1; string field2 = 2; int64 field3 = 3; } message request { string name = 1; hugemessage payload = 2; } message rawrequest { string name = 1; bytes payload = 2; }
Der folgende Code:
req1, err := proto.Marshal(&pb.Request{ Name: "name", Payload: &pb.HugeMessage{ Field1: []byte{1, 2, 3}, Field2: "test", Field3: 948414, }, }) if err != nil { panic(err) } huge, err := proto.Marshal(&pb.HugeMessage{ Field1: []byte{1, 2, 3}, Field2: "test", Field3: 948414, }) if err != nil { panic(err) } req2, err := proto.Marshal(&pb.RawRequest{ Name: "name", Payload: huge, }) if err != nil { panic(err) } fmt.Printf("equal? %t\n", bytes.Equal(req1, req2))
Ausgabe equal? true
Es ist unklar, ob diese „Eigenart“ völlig zuverlässig ist, und es gibt keine Garantie dafür, dass sie auf unbestimmte Zeit weiter funktioniert. Offensichtlich rawrequest
类型必须完全镜像 request
Typen, das ist nicht ideal.
Eine andere Möglichkeit besteht darin, die Nachricht manueller zu erstellen, d. h. mit dem protowire-Paket – auch hier gilt: Vorsicht ist geboten.
Das obige ist der detaillierte Inhalt vonKann ich eine vorhandene Protobuf-Binärdatei beim Marshallen der darin enthaltenen Nachrichten wiederverwenden? (protobuf3). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!