第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

在編組包含它的消息時(shí),我可以重用現(xiàn)有的 protobuf 二進(jìn)制文件嗎?(protobuf3)

在編組包含它的消息時(shí),我可以重用現(xiàn)有的 protobuf 二進(jìn)制文件嗎?(protobuf3)

Go
呼如林 2023-03-15 15:26:07
Protobuf 的定義是這樣的:syntax = "proto3"message HugeMessage {    // omitted}message Request {    string name = 1;    HugeMessage payload = 2;}在某種情況下,我HugeMessage從某人那里收到了一個(gè)消息,我想用額外的字段將其打包,然后將消息傳輸給其他人。因此,我必須將二進(jìn)制文件解HugeMessage組為 Go 結(jié)構(gòu),將其打包為Request,然后再次編組。由于 的 hgue 大小, Unmarshal和MarshalHugeMessage的成本無法承受。那么我可以在不更改 protobuf 定義的情況下重用二進(jìn)制文件嗎?HugeMessagefunc 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)}
查看完整描述

2 回答

?
繁星coding

TA貢獻(xiàn)1797條經(jīng)驗(yàn) 獲得超4個(gè)贊

簡短的回答是:不,沒有簡單或標(biāo)準(zhǔn)的方法來實(shí)現(xiàn)這一點(diǎn)。


最明顯的策略是按照您當(dāng)前的方式進(jìn)行 - 解組HugeMessage,將其設(shè)置為Request,然后再次編組。golang protobuf API 表面并沒有真正提供一種方法來做更多的事情——這是有充分理由的。


也就是說,有多種方法可以實(shí)現(xiàn)您想要做的事情。但這些不一定安全或可靠,所以你必須權(quán)衡成本與你現(xiàn)在擁有的成本。


避免解組的一種方法是利用消息通常序列化的方式;


message Request {

    string name = 1;

    HugeMessage payload = 2;

}

.. 相當(dāng)于


message Request {

    string name = 1;

    bytes payload = 2;

}

.. 其中包含針對(duì)某些payload調(diào)用的結(jié)果。Marshal(...)HugeMessage


所以,如果我們有以下定義:


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;

}

以下代碼:


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

產(chǎn)出equal? true


這個(gè)“怪癖”是否完全可靠尚不清楚,也不能保證它會(huì)無限期地繼續(xù)工作。顯然,RawRequest類型必須完全反映Request類型,這并不理想。


另一種選擇是以更手動(dòng)的方式構(gòu)建消息,即使用protowire包 - 同樣,隨意,建議謹(jǐn)慎。


查看完整回答
反對(duì) 回復(fù) 2023-03-15
?
守候你守候我

TA貢獻(xiàn)1802條經(jīng)驗(yàn) 獲得超10個(gè)贊

很快,它可以通過protowire完成,如果重用的結(jié)構(gòu)不復(fù)雜的話,這并不難。

根據(jù)protobuf的編碼章節(jié),協(xié)議緩沖區(qū)消息是一系列字段值對(duì),這些對(duì)的順序無關(guān)緊要。我想到了一個(gè)明顯的想法:就像 protoc 編譯器一樣工作,手動(dòng)組成嵌入字段并將其附加到請(qǐng)求的末尾。

在這種情況下,我們想重用HugeMessagein?Request,所以字段的鍵值對(duì)將是2:{${HugeMessageBinary}}。所以代碼(有點(diǎn)不同)可能是:

func binaryEmbeddingImplementation(messageBytes []byte, name string) (requestBytes []byte, err error) {

? ? // 1. create a request with all ready except the payload. and marshal it.

? ? request := protodef.Request{

? ? ? ? Name: name,

? ? }

? ? requestBytes, err = proto.Marshal(&request)

? ? if err != nil {

? ? ? ? return nil, err

? ? }

? ? // 2. manually append the payload to the request, by protowire.

? ? requestBytes = protowire.AppendTag(requestBytes, 2, protowire.BytesType) //? embedded message is same as a bytes field, in wire view.

? ? requestBytes = protowire.AppendBytes(requestBytes, messageBytes)

? ? return requestBytes, nil

}


告訴字段號(hào),字段類型和字節(jié),就是這樣。常見的方式就是這樣。


func commonImplementation(messageBytes []byte, name string) (requestBytes []byte, err error) {

? ? // receive it from file or network, not important.

? ? var message protodef.HugeMessage

? ? _ = proto.Unmarshal(messageBytes, &message) // slow

? ? request := protodef.Request{

? ? ? ? Name:? ? name,

? ? ? ? Payload: &message,

? ? }

? ? return proto.Marshal(&request) // slow

}

一些基準(zhǔn)。


$ go test -bench=a -benchtime 10s ./pkg/? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

goos: darwin

goarch: arm64

pkg: pbembedding/pkg

BenchmarkCommon-8? ? ? ? ? ? ?49? ? ? ? ?288026442 ns/op

BenchmarkEmbedding-8? ? ? ? ?201? ? ? ? ?176032133 ns/op

PASS

ok? ? ? pbembedding/pkg 80.196s


package pkg


import (

? ? "github.com/stretchr/testify/assert"

? ? "golang.org/x/exp/rand"

? ? "google.golang.org/protobuf/proto"

? ? "pbembedding/pkg/protodef"

? ? "testing"

)


var hugeMessageSample = receiveHugeMessageFromSomewhere()


func TestEquivalent(t *testing.T) {

? ? requestBytes1, _ := commonImplementation(hugeMessageSample, "xxxx")

? ? requestBytes2, _ := binaryEmbeddingImplementation(hugeMessageSample, "xxxx")

? ? // They are not always equal int bytes. you should compare them in message view instead of binary from

? ? // due to: https://developers.google.com/protocol-buffers/docs/encoding#implications

? ? // I'm Lazy.

? ? assert.NotEmpty(t, requestBytes1)

? ? assert.Equal(t, requestBytes1, requestBytes2)

? ? var request protodef.Request

? ? err := proto.Unmarshal(requestBytes1, &request)

? ? assert.NoError(t, err)

? ? assert.Equal(t, "xxxx", request.Name)

}


// actually mock one.

func receiveHugeMessageFromSomewhere() []byte {

? ? buffer := make([]byte, 1024*1024*1024)

? ? _, _ = rand.Read(buffer)

? ? message := protodef.HugeMessage{

? ? ? ? Data: buffer,

? ? }

? ? res, _ := proto.Marshal(&message)

? ? return res

}


func BenchmarkCommon(b *testing.B) {

? ? b.ResetTimer()

? ? for i := 0; i < b.N; i++ {

? ? ? ? _, err := commonImplementation(hugeMessageSample, "xxxx")

? ? ? ? if err != nil {

? ? ? ? ? ? panic(err)

? ? ? ? }

? ? }

}


func BenchmarkEmbedding(b *testing.B) {

? ? b.ResetTimer()

? ? for i := 0; i < b.N; i++ {

? ? ? ? _, err := binaryEmbeddingImplementation(hugeMessageSample, "xxxx")

? ? ? ? if err != nil {

? ? ? ? ? ? panic(err)

? ? ? ? }

? ? }

}


查看完整回答
反對(duì) 回復(fù) 2023-03-15
  • 2 回答
  • 0 關(guān)注
  • 294 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)