protobuf est défini comme suit :
syntax = "proto3" message hugemessage { // omitted } message request { string name = 1; hugemessage payload = 2; }
Dans un cas, j'ai reçu un binaire hugemessage
,我想用其他字段打包它,然后将该消息传输给其他人。因此,我必须将 hugemessage
二进制文件unmarshal放入go结构中,将其打包到request
中,然后再次marshal。由于 hugemessage
的 hgue 大小,unmarshal 和 marshal 的成本难以承受。那么我可以重用 hugemessage
de quelqu'un sans changer la définition de protobuf ?
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) }
La réponse courte est : Non, il n'existe pas de moyen simple ou standard d'y parvenir.
La stratégie la plus évidente est de procéder comme vous le faites actuellement : démarrer hugemessage
,将其设置为 request
, puis rassembler à nouveau. La surface de l'API Golang protobuf ne permet pas vraiment d'en faire plus - et pour cause.
Cela dit, il existe façons de réaliser ce que vous voulez faire. Mais ceux-ci ne sont pas nécessairement sûrs ou fiables, vous devez donc comparer ce coût à ce dont vous disposez actuellement.
Une façon d'éviter le désorganisation est de profiter de la façon dont les messages sont normalement sérialisés
;message request { string name = 1; hugemessage payload = 2; }
..équivalent à
message request { string name = 1; bytes payload = 2; }
.. où payload
包含针对某些 hugemessage
调用 marshal(...)
est le résultat.
Donc, si on a la définition suivante :
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; }
Le code suivant :
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))
Sortie equal? true
On ne sait pas si cette « bizarrerie » est totalement fiable, et rien ne garantit qu’elle continuera à fonctionner indéfiniment. Evidemment rawrequest
类型必须完全镜像 request
les types, ce n'est pas l'idéal.
Une autre option consiste à créer le message de manière plus manuelle, c'est-à-dire en utilisant le package protowire - encore une fois, n'hésitez pas, la prudence est recommandée.
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!