Bolehkah saya menggunakan semula perduaan protobuf sedia ada semasa menyusun mesej yang mengandunginya? (protobuf3)

WBOY
Lepaskan: 2024-02-06 10:30:11
ke hadapan
487 orang telah melayarinya

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

Kandungan soalan

protobuf ditakrifkan seperti berikut:

syntax = "proto3"

message hugemessage {
    // omitted
}

message request {
    string name = 1;
    hugemessage payload = 2;
}
Salin selepas log masuk

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

Salin selepas log masuk


Jawapan Betul


Jawapan ringkasnya ialah: Tidak, tiada cara mudah atau standard untuk mencapai ini.

Strategi yang paling jelas ialah melakukannya seperti yang anda lakukan sekarang - unmarshal hugemes​​sage,将其设置为 request dan kemudian marshal lagi. Permukaan API protobuf Golang tidak benar-benar menyediakan cara untuk melakukan lebih banyak - dan untuk alasan yang baik.

Maksudnya, terdapat cara untuk mencapai apa yang anda mahu lakukan. Tetapi ini tidak semestinya selamat atau boleh dipercayai, jadi anda perlu menimbang kos itu dengan apa yang anda miliki sekarang.

Satu cara untuk mengelakkan pembongkaran adalah dengan memanfaatkan cara mesej biasanya bersiri

message request {
    string name = 1;
    hugemessage payload = 2;
}
Salin selepas log masuk

..bersamaan dengan

message request {
    string name = 1;
    bytes payload = 2;
}
Salin selepas log masuk

.. mana payload 包含针对某些 hugemes​​sage 调用 marshal(...) hasilnya.

Jadi, jika kita mempunyai definisi berikut:

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;
}
Salin selepas log masuk

Kod berikut:

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))
Salin selepas log masuk

Output equal? true

Tidak jelas sama ada "kebiasaan" ini boleh dipercayai sepenuhnya, dan tiada jaminan ia akan terus berfungsi selama-lamanya. Jelas sekali rawrequest 类型必须完全镜像 request jenis, ini tidak sesuai.

Pilihan lain ialah membina mesej dengan cara yang lebih manual, iaitu menggunakan pakej protowire - sekali lagi, jangan ragu, berhati-hati disyorkan.

Atas ialah kandungan terperinci Bolehkah saya menggunakan semula perduaan protobuf sedia ada semasa menyusun mesej yang mengandunginya? (protobuf3). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan