Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I dump the struct into the byte array without reflection?

Tags:

I already found encoding/binary package to deal with it, but it depended on reflect package so it didn't work with uncapitalized(that is, unexported) struct fields. However I spent a week to find that problem out, I still have a question: if struct fields should not be exported, how do I dump them easily into binary data?

EDIT: Here's the example. If you capitalize the name of fields of Data struct, that works properly. But Data struct was intended to be an abstract type, so I don't want to export these fields.

package main import (     "fmt"     "encoding/binary"     "bytes" )  type Data struct {     id int32     name [16]byte }   func main() {     d := Data{Id: 1}     copy(d.Name[:], []byte("tree"))     buffer := new(bytes.Buffer)     binary.Write(buffer, binary.LittleEndian, d)     // d was written properly     fmt.Println(buffer.Bytes())     // try to read...     buffer = bytes.NewBuffer(buffer.Bytes())     var e = new(Data)     err := binary.Read(buffer, binary.LittleEndian, e)     fmt.Println(e, err) } 
like image 256
kroisse Avatar asked Oct 12 '12 07:10

kroisse


1 Answers

Your best option would probably be to use the gob package and let your struct implement the GobDecoder and GobEncoder interfaces in order to serialize and deserialize private fields.

This would be safe, platform independent, and efficient. And you have to add those GobEncode and GobDecode functions only on structs with unexported fields, which means you don't clutter the rest of your code.

func (d *Data) GobEncode() ([]byte, error) {     w := new(bytes.Buffer)     encoder := gob.NewEncoder(w)     err := encoder.Encode(d.id)     if err!=nil {         return nil, err     }     err = encoder.Encode(d.name)     if err!=nil {         return nil, err     }     return w.Bytes(), nil }  func (d *Data) GobDecode(buf []byte) error {     r := bytes.NewBuffer(buf)     decoder := gob.NewDecoder(r)     err := decoder.Decode(&d.id)     if err!=nil {         return err     }     return decoder.Decode(&d.name) }  func main() {     d := Data{id: 7}     copy(d.name[:], []byte("tree"))     buffer := new(bytes.Buffer)     // writing     enc := gob.NewEncoder(buffer)     err := enc.Encode(d)     if err != nil {         log.Fatal("encode error:", err)     }     // reading     buffer = bytes.NewBuffer(buffer.Bytes())     e := new(Data)     dec := gob.NewDecoder(buffer)     err = dec.Decode(e)     fmt.Println(e, err) } 
like image 166
Denys Séguret Avatar answered Nov 09 '22 20:11

Denys Séguret