猿问

可以将 protobuf 编组消息发送到已分配的字节数组而无需复制吗?

我正在通过自定义数据包实现客户端服务器通信。我正在使用围棋net.conn。可以拨号tcp/unix schemes,非常方便。我用来protocol buffer定义我的消息。


我定义了一个包含length和buffer


type Packet struct {

    length uint32

    buffer []byte

}

API函数是这样的:

func(api *API) Send(m *proto.Message) error

func(api *API) Receive(p *Packet) error


以send函数为例,它接收一个 protobuf 消息,将其编组为Packet. 并将其写入net.conn.


下面是 Send 函数的简化版本:


func(api *API) Send(m *proto.Message) error {

    bytes, err := proto.Marshal(m)

    if err != nil {

        return err

    }

    buffer := api.packet[:length]

    copy(buffer, bytes)

    _, err := api.conn.Write(buffer)

    if err != nil {

        return err

    }

    return nil

}

我正在复制bytes到buffer. 因为 Go protocol buffer API 只提供

func Marshal(pb Message) ([]byte, error)


在 Protocol Buffer C++ 中,它提供了 bool SerializeToArray(void * data, int size) const,它正在序列化消息并将其存储在给定的字节数组中。但是我在 Go protocol buffer API 中找不到同样的东西。


如果我想直接将序列化结果存储在给定的字节数组中,有什么办法可以避免复制?


慕妹3146593
浏览 126回答 3
3回答

慕田峪9158850

您正在寻找来自 的MarshalTo方法gogo/protobuf,它是 protobuf 的另一种实现,与原始方法兼容。当您将要填充的缓冲区传递给它时,您可以通过多个编组调用重新使用同一个缓冲区。显然缓冲区应该足够大。func MarshalTo([]byte, m) error

慕码人2483693

似乎你可以Packet.buffer成为一个proto.Buffertype Packet struct {    length uint32    buffer proto.Buffer}...var packet Packetpacket.length = YouLengthpacket.buffer = proto.NewBuffer(make([]byte, YouLength))//Then you can Marshall in Packet directly and it  may be reused.err := packet.Marshal(message)

RISEBY

目前尚不清楚你在问什么。请注意,原型 Marshal() 函数完全符合您的要求:它将消息序列化为字节切片(您可能指的是字节数组)看看这些是否有帮助:func(api *API) Send(m *proto.Message) error {    p := Packet{}    p.buffer, err := proto.Marshal(m)    if err != nil {        return err    }    _, err := api.conn.Write(p.buffer)    if err != nil {        return err    }    return nil}或者func(api *API) Send(m *proto.Message) error {    buffer := api.packet[:length]    buffer, err := proto.Marshal(m)    if err != nil {        return err    }    _, err := api.conn.Write(buffer)    if err != nil {        return err    }    return nil}
随时随地看视频慕课网APP

相关分类

Go
我要回答