golang 对struct进行Serialize的方法,即将存取二进制文件到struct的方法

方法一:

serialize 的标准方法:

使用gobbase64 或 base58。

 

 

方法二:

下面是自己实现的 serialize 方法,不推荐自己实现,应该用标准方法。

代码如下:

package main

import (
    "bytes"
    "encoding/binary"
    "fmt"
    "log"
    "os"
)

//this type represnts a record with three fields
type payload struct {
    Three int32
}

func main() {
    writeFile()
    readFile()
}

func readFile() {
    file, err := os.Open("test.bin")
    defer file.Close()
    if err != nil {
        log.Fatal(err)
    }

    m := payload{}
    for i := 0; i < 10; i++ {
        data := readNextBytes(file, 4)
        buffer := bytes.NewBuffer(data)
        err = binary.Read(buffer, binary.BigEndian, &m)
        if err != nil {
            log.Fatal("binary.Read failed", err)
        }

        fmt.Println("m is: ", m)
    }
}

func readNextBytes(file *os.File, number int) []byte {
    bytes := make([]byte, number)

    _, err := file.Read(bytes)
    if err != nil {
        log.Fatal(err)
    }

    return bytes
}

func writeFile() {
    file, err := os.Create("test.bin")
    defer file.Close()
    if err != nil {
        log.Fatal(err)
    }

    for i := 0; i < 10; i++ {
        s := &payload{
            int32(i),
        }
        fmt.Println(s)
        var bin_buf bytes.Buffer
        binary.Write(&bin_buf, binary.BigEndian, s)

        b := bin_buf.Bytes()
        l := len(b)
        fmt.Println("write len: ", l)

        writeNextBytes(file, b)
    }
}

func writeNextBytes(file *os.File, bytes []byte) {
    _, err := file.Write(bytes)

    if err != nil {
        log.Fatal(err)
    }
}

 

除了将数据放进结构体之外,你还可以直接将数据放进结构体对象的某个成员里:

binary.Read(buffer, binary.BigEndian, &m.Two)

不过要保证buffer与成员的内存长度一样。

 

# 注意,这里必须注意payload结构里的任何field成员都不能是 int,必须制定成员的byte长度,也即必须使用 int32, int64, float32等等,不能使用 int, float。因为不指定长度若将它存到磁盘并读取回来时会产生歧义,不知道读写多少个byte的。

另外,如果出现这种错误: reflect: reflect.Value.SetUint using value obtained using unexported field, 是因为payload结构体内的Field的名称小写引起的,改成首字母大写即可。

如果你向确认结构体是否被正确的赋值了,可以:

bs := make([]byte, 4)
binary.LittleEndian.PutUint32(bs, 31415926)
fmt.Println(bs)

 

posted @ 2018-06-15 17:07  微信公众号--共鸣圈  阅读(2088)  评论(0编辑  收藏  举报