Maison > développement back-end > Golang > le corps du texte

Puis-je réutiliser un binaire protobuf existant lors du regroupement des messages le contenant ? (protobuf3)

WBOY
Libérer: 2024-02-06 10:30:11
avant
495 Les gens l'ont consulté

在编组包含它的消息时,我可以重用现有的 protobuf 二进制文件吗?(protobuf3)

Contenu de la question

protobuf est défini comme suit :

syntax = "proto3"

message hugemessage {
    // omitted
}

message request {
    string name = 1;
    hugemessage payload = 2;
}
Copier après la connexion

Dans un cas, j'ai reçu un binaire hugemes​​sage,我想用其他字段打包它,然后将该消息传输给其他人。因此,我必须将 hugemes​​sage 二进制文件unmarshal放入go结构中,将其打包到request中,然后再次marshal。由于 hugemes​​sage 的 hgue 大小,unmarshalmarshal 的成本难以承受。那么我可以重用 hugemes​​sage 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)
}

Copier après la connexion


Bonne réponse


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 hugemes​​sage,将其设置为 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;
}
Copier après la connexion

..équivalent à

message request {
    string name = 1;
    bytes payload = 2;
}
Copier après la connexion

.. où payload 包含针对某些 hugemes​​sage 调用 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;
}
Copier après la connexion

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))
Copier après la connexion

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!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal