doudan1123 2012-10-12 07:20
浏览 27
已采纳

如何在不反射的情况下将结构转储到字节数组中?

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)
}
  • 写回答

1条回答 默认 最新

  • dsjojts9734 2012-10-12 07:59
    关注

    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)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 划分vlan后不通了
  • ¥15 GDI处理通道视频时总是带有白色锯齿
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)
  • ¥15 自适应 AR 模型 参数估计Matlab程序
  • ¥100 角动量包络面如何用MATLAB绘制
  • ¥15 merge函数占用内存过大
  • ¥15 使用EMD去噪处理RML2016数据集时候的原理
  • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大