序列化结构字段以预存现有的字节片
I have a setup where I receive data over the network and serialize it to my struct. It works fine, but now I need to serialize the data to a slice buffer to send it across the network.
I am trying to avoid having to allocate more than needed so I have already set up a buffer which I like to write to for all my serializing. But am not sure how to do this.
My setup is like this:
recieveBuffer := make([]byte, 1500)
header := recieveBuffer[0:1]
message := recieveBuffer[1:]
So I am trying to write fields from a struct to message
and the total number of bytes for all the fields as a value for header
.
This was how I deserialized to the struct:
// Deserialize ...
func (userSession *UserSession) Deserialize(message []byte) {
userSession.UID = int64(binary.LittleEndian.Uint32(message[0:4]))
userSession.UUID = string(message[4:40])
userSession.Username = string(message[40:])
}
I don't really know how to do the reverse of this, however. Is it possible without creating buffers for each field I want to serialize before copying to message
?
我有一个设置,可以通过网络接收数据并将其序列化为我的结构。 它可以正常工作,但是现在我需要将数据序列化到切片缓冲区,以通过网络发送它。 p>
我试图避免分配过多的数据,所以我已经设置了 缓冲区,我想为所有序列化写一个缓冲区。 p>
我的设置如下: p>
recieveBuffer:= make([] byte,1500 )
header:= recieveBuffer [0:1]
message:= recieveBuffer [1:]
code> pre>
所以我试图将字段从结构体写入 message code>和所有字段的总字节数作为 header code>的值。 p>
这就是我反序列化到struct的方式:
//反序列化...
func(userSession * UserSession)反序列化(消息[] byte){
userSession.UID = int64(binary.LittleEndian.Uint32(message [ 0:4])))
userSession.UUID =字符串(消息[4:40])
userSession.Username =字符串(消息[40:])
}
code> pre>
但是,我真的不知道该怎么做。 p>
div>在复制到 message code>之前,是否无需为要序列化的每个字段创建缓冲区?
Given the preallocated buffer buf
, you can reverse the process like this:
buf[0] = byte(40+len(userSession.Username))
binary.LittleEndian.PutUint32(buf[1:], uint32(int32(userSession.UID)))
copy(buf[5:41], userSession.UUID)
copy(buf[41:], userSession.Username)
Given two helper functions.
One to encode a primitive to a byte slice:
func EncodeNumber2NetworkOrder(v interface{}) ([]byte, error) {
switch v.(type) {
case int: // int is at least 32 bits
b := make([]byte, 4)
binary.BigEndian.PutUint32(b, uint32(v.(int)))
return b, nil
case int8:
b := []byte{byte(v.(int8))}
return b, nil
// ... truncated
and one to convert primitive, non-byte slices to a byte slice
func EncodeBigEndian(in []float64) []byte {
var out []byte = make([]byte, len(in)*8)
var wg sync.WaitGroup
wg.Add(len(in))
for i := 0; i < len(in); i++ {
go func(out *[]byte, i int, f float64) {
defer wg.Done()
binary.BigEndian.PutUint64((*out)[(i<<3):], math.Float64bits(f))
}(&out, i, in[i])
}
wg.Wait()
return out
}
your binary serialization might look like this for a bogus struct like
type Foo struct {
time int64
data []float64
}
func Encode(f *Foo) []byte {
da := encoder.EncodeBigEndian(f.data)
bytes := make([]byte,0)
bytes = append(bytes, da...)
return bytes
}