我如何转储到结构不反射的字节数组? [英] How do I dump the struct into the byte array without reflection?

查看:186
本文介绍了我如何转储到结构不反射的字节数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经找到编码/二进制包对付它,但它依靠的反映包,以便它不与小写形式工作(即,取消导出)结构域。不过,我花了一个星期来发现问题出来了,我还有一个问题:如果结构字段不应该出口,我怎么甩掉他们很容易地转换成二进制数据。

编辑:这里的例子。如果利用数据结构的字段的名称,即正常工作。但数据结构意欲是一个抽象类,所以我不希望导出这些字段。

主包
进口(
    FMT
    编码/二进制
    字节
)类型数据结构{
    ID INT32
    名字[16]字节
}
FUNC的main(){
    D:= {数据编号:1}
    副本(d.Name [:],[]字节(树))
    缓冲区:=新(bytes.Buffer)
    binary.Write(缓冲,binary.LittleEndian,D)
    //天得到了正确写入
    fmt.Println(buffer.Bytes())
    //尝试读取...
    缓冲= bytes.NewBuffer(buffer.Bytes())
    变种E =新的(数据)
    错误:= binary.Read(缓冲,binary.LittleEndian,E)
    fmt.Println(即错误)
}


解决方案

您最好的选择很可能是使用采空包,让你的结构实现 GobDe codeR 并的GobEn$c$cr 为了接口,序列化和反序列化的私人领域。

这将是安全的,独立于平台,高效。而且你要添加这些GobEn code和GobDe code函数只与未导出字段结构,这意味着你不会堆积在code的其余部分。

  FUNC(D *数据)GobEn code()([]字节,错误){
    W:=新(bytes.Buffer)
    EN codeR:= gob.NewEn codeR(W)
    错误:= EN coder.En code(d.id)
    如果犯错!= {为零
        返回nil,ERR
    }
    ERR = EN coder.En code(d.name)
    如果犯错!= {为零
        返回nil,ERR
    }
    返回w.Bytes(),零
}FUNC(D *数据)GobDe code(BUF []字节)的错误{
    R:= bytes.NewBuffer(BUF)
    德codeR:= gob.NewDe codeR(R)
    错误:=去coder.De code(安培; d.id)
    如果犯错!= {为零
        返回ERR
    }
    返回德coder.De code(安培; d.name)
}FUNC的main(){
    D:= {数据ID:7}
    副本(d.name [:],[]字节(树))
    缓冲区:=新(bytes.Buffer)
    // 写作
    ENC:= gob.NewEn codeR(缓冲)
    错误:= enc.En code(D)
    如果犯错!= {为零
        log.Fatal(EN code错误:ERR)
    }
    // 读
    缓冲= bytes.NewBuffer(buffer.Bytes())
    E:=新的(数据)
    12月:= gob.NewDe codeR(缓冲)
    ERR = dec.De code(E)
    fmt.Println(即错误)
}

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

解决方案

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

这篇关于我如何转储到结构不反射的字节数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆