Heim  >  Artikel  >  Backend-Entwicklung  >  Kann ich eine vorhandene Protobuf-Binärdatei beim Marshallen der darin enthaltenen Nachrichten wiederverwenden? (protobuf3)

Kann ich eine vorhandene Protobuf-Binärdatei beim Marshallen der darin enthaltenen Nachrichten wiederverwenden? (protobuf3)

WBOY
WBOYnach vorne
2024-02-06 10:30:11436Durchsuche

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

Frageninhalt

protobuf ist wie folgt definiert:

syntax = "proto3"

message hugemessage {
    // omitted
}

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

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


Richtige Antwort


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 hugemes​​sage,将其设置为 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 包含针对某些 hugemes​​sage 调用 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!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen