Maison  >  Article  >  développement back-end  >  Puis-je réutiliser un binaire protobuf existant lors du regroupement des messages le contenant ? (protobuf3)

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

WBOY
WBOYavant
2024-02-06 10:30:11478parcourir

在编组包含它的消息时,我可以重用现有的 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;
}

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)
}


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;
}

..équivalent à

message request {
    string name = 1;
    bytes payload = 2;
}

.. 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;
}

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer