我有一个设置,我通过网络接收数据并将其序列化到我的结构。它工作正常,但现在我需要将数据序列化到切片缓冲区以通过网络发送它。
我试图避免分配超过需要的数量,所以我已经设置了一个缓冲区,我喜欢写所有的序列化。但我不确定该怎么做。
我的设置是这样的:
recieveBuffer := make([]byte, 1500)
header := recieveBuffer[0:1]
message := recieveBuffer[1:]
所以我试图将结构中的字段写入message
,并将所有字段的总字节数作为header
的值。
这就是我对结构反序列化的方式:
// 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:])
}
但是,我并不知道如何做到这一点。是否可以在复制到message
之前不为每个我要序列化的字段创建缓冲区?
答案 0 :(得分:1)
给定预分配的缓冲区buf
,您可以像这样反转该过程:
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)
答案 1 :(得分:0)
给出两个辅助函数。
将基元编码为字节切片的一个:
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
和一个将原始的非字节切片转换为字节切片
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
}
对于像
这样的虚假结构,你的二进制序列化可能看起来像这样 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
}