2017-12-19 2 views
0

Ich habe ein Setup, wo ich Daten über das Netzwerk und serialisieren es in meine Struktur. Es funktioniert gut, aber jetzt muss ich die Daten zu einem Schnittpuffer serialisieren, um es über das Netzwerk zu senden.Serialize struct Felder zu vor vorhandenen Stück von Bytes

Ich versuche zu vermeiden, mehr als erforderlich zu reservieren, so habe ich bereits einen Puffer eingerichtet, die ich gerne für alle meine Serialisierung schreiben würde. Aber ich bin mir nicht sicher, wie ich das machen soll.

Mein Setup ist wie folgt:

recieveBuffer := make([]byte, 1500) 
header := recieveBuffer[0:1] 
message := recieveBuffer[1:] 

So Felder Ich versuche, aus einer Struktur für header-message und die Gesamtzahl der Bytes für alle Felder als Wert zu schreiben.

Dies war, wie ich auf die Struktur deserialisiert:

// 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:]) 
} 

ich nicht wirklich wissen, wie man das Gegenteil davon zu tun, aber. Ist es möglich, ohne Puffer für jedes Feld zu erstellen, das ich vor dem Kopieren auf message serialisieren möchte?

Antwort

1

den vorreservierten Puffer buf, Da Sie den Prozess wie folgt umkehren:

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

Gegeben zwei Hilfsfunktionen.

Eine primitiven auf eine Byte Scheibe zu kodieren:

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 

und eine primitiven, nicht-Byte-Scheiben

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 
} 

Ihre binäre Serialisierung auf eine Byte Scheibe zu konvertieren aussehen könnte dies für eine falsche Struktur wie

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 
}