Go 是否可以将protobuf封送处理消息转到已分配的字节数组而不复制?

Go 是否可以将protobuf封送处理消息转到已分配的字节数组而不复制?,go,protocol-buffers,ipc,packet,Go,Protocol Buffers,Ipc,Packet,我正在通过自定义数据包实现客户机-服务器通信。 我正在使用Gonet.conn。它可以拨打非常方便的tcp/unix方案。我使用协议缓冲区来定义我的消息 我定义了一个包含长度和缓冲区 type Packet struct { length uint32 buffer []byte } API函数如下所示: func(api*api)发送(m*proto.Message)错误 func(api*api)接收(p*数据包)错误 以send函数为例,它接收protobuf消息,将其封

我正在通过自定义数据包实现客户机-服务器通信。 我正在使用Go
net.conn
。它可以拨打非常方便的tcp/unix方案。我使用
协议缓冲区
来定义我的消息

我定义了一个包含
长度
缓冲区

type Packet struct {
    length uint32
    buffer []byte
}
API函数如下所示:
func(api*api)发送(m*proto.Message)错误

func(api*api)接收(p*数据包)错误

send
函数为例,它接收protobuf消息,将其封送到
数据包中
。并将其写入
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
}
我正在将
字节
复制到
缓冲区
。因为Go协议缓冲区API只提供
func封送处理(pb消息)([]字节,错误)

<>协议缓冲区C++
bool SerializeToArray(void*data,int size)const
,它序列化消息并将其存储在给定的字节数组中。 但我在Go协议缓冲区API中找不到同样的东西


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

不清楚你在问什么。请注意,proto 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
}


似乎您可以将
数据包.buffer
作为

您正在从
gogo/protobuf
中寻找方法,这是protobuf的另一个实现,与原始版本兼容

当您将要填充的缓冲区传递给同一缓冲区时,可以通过多个封送处理调用重复使用该缓冲区。显然,缓冲区应该足够大

func MarshalTo([]byte, m) error 

你能澄清几件事吗:为什么数据包存储在API的字段中,这个长度是从哪里来的?你真的只想写一个由长度(4字节)组成的字节数组,然后将实际消息写入连接吗?接受答案怎么样?我的目的是将序列化缓冲区放入
数据包中,而不是直接将其写入
conn
。因为包已经被其他组件用于我的项目。我不能重构它
proto.Marshal
返回
[]字节
,并被复制到我的数据包中。我正在寻找一种避免复制的方法。一个例子是原BuffC++ C++,它可以将消息整理成一个已经分配的缓冲区。但是go protobuf只能退回它。
type Packet struct {
    length uint32
    buffer proto.Buffer
}
...
var packet Packet
packet.length = YouLength
packet.buffer = proto.NewBuffer(make([]byte, YouLength))
//Then you can Marshall in Packet directly and it  may be reused.
err := packet.Marshal(message)
func MarshalTo([]byte, m) error