博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go Web:数据存储(3)——gob对象序列化
阅读量:6945 次
发布时间:2019-06-27

本文共 3712 字,大约阅读时间需要 12 分钟。

序列化持久存储gob

本篇文章仍然接前面的文章:,主要介绍将博客文章数据序列化持久到文件中。

encoding/gob包用于编码器和解码器之间进行二进制流的数据交换,例如发送端和接收端之间交换数据。也能用来实现对象序列化,并持久保存的功能,然后再需要的时候加载并解码成原始数据。

gob包的用法很简单,但有必要去了解它的背景知识,见官方手册:

下面是序列化到文件中的函数代码:

func storeToGob(data interface{}, filename string) {    buffer := new(bytes.Buffer)    encoder := gob.NewEncoder(buffer)    err := encoder.Encode(data)    if err != nil {        panic(err)    }    err = ioutil.WriteFile(filename, buffer.Bytes(), 0600)    if err != nil {        panic(err)    }}

其中gob.NewEncoder()函数用来生成一个gob的流编码器。通过编码器的Encode()方法,可以将数据编码成二进制格式,Encode()方法的参数类型是interface{},所以storeToGob()函数的第一个参数也指定为此类型可以将任意数据结构序列化。然后只需将序列化到buffer中的数据写入到文件中即可。

需要注意的是上面使用ioutil.WriteFile()函数会在文件存在时进行截断,文件不存在时以给定权限(上面给的权限是600)进行文件创建。

另外,gob不会序列化指针,它会找到指针所指向的数据对象,并对数据对象进行序列化

因为这个函数接受任意类型的数据结构,所以可以将map类型的PostById和PostByAuthor进行序列化,也可以将Post类型的单篇文章进行序列化。

storeToGob(PostById, "d:/PostById.gob")storeToGob(PostByAuthor, "d:/PostByAuthor.gob")storeToGob(post3, "d:/post3.gob")

序列化之后,可以加载序列化后的文件进行解码。加载gob文件并解码二进制数据的函数如下:

func load(data interface{}, filename string) {    raw, err := ioutil.ReadFile(filename)    if err != nil {        panic(err)    }    buffer := bytes.NewBuffer(raw)    dec := gob.NewDecoder(buffer)    err = dec.Decode(data)    if err != nil {        panic(err)    }}

逻辑很简单,从文件中读取数据,并解码后保存到data中。

唯一需要注意的是解码器的解码方法Decode()的参数虽然是interface{}类型的,但却要求只能是指针类型。如果传参时传递的是非指针类型,将报错。

例如,分别解码前文保存的3个gob文件,并分别保存到对应的数据结构中:

load(&PostById, "d:/PostById.gob")fmt.Println(PostById[1])fmt.Println(PostById[2])load(&PostByAuthor, "d:/PostByAuthor.gob")for _, post := range PostByAuthor["userA"] {    fmt.Println(post)}var post33 *Postload(&post33, "d:/post3.gob")fmt.Println(post33)

注意上面调用load()函数时,传递的第一个参数都是指针类型的。post33变量自身就是指针,所以上面load(post33,"d:/post3.gob")也是可行的,但传递post33&post33的结果是不一样的,如下:

// load(post33, "d:/post3.gob"){3 Hello 3 userC}// load(&post33, "d:/post3.gob")&{3 Hello 3 userC}

现在数据又回到了内存存储结构上,可以进行正常的增、删、改、查等操作。

下面是完整的代码:

package mainimport (    "bytes"    "encoding/gob"    "fmt"    "io/ioutil")type Post struct {    Id      int    Content string    Author  string}var PostById map[int]*Postvar PostByAuthor map[string][]*Postfunc store(post *Post) {    PostById[post.Id] = post    PostByAuthor[post.Author] = append(PostByAuthor[post.Author], post)}func storeToGob(data interface{}, filename string) {    buffer := new(bytes.Buffer)    encoder := gob.NewEncoder(buffer)    err := encoder.Encode(data)    if err != nil {        panic(err)    }    err = ioutil.WriteFile(filename, buffer.Bytes(), 0600)    if err != nil {        panic(err)    }}func load(data interface{}, filename string) {    raw, err := ioutil.ReadFile(filename)    if err != nil {        panic(err)    }    buffer := bytes.NewBuffer(raw)    dec := gob.NewDecoder(buffer)    err = dec.Decode(data)    if err != nil {        panic(err)    }}func main() {    PostById = make(map[int]*Post)    PostByAuthor = make(map[string][]*Post)    post1 := &Post{Id: 1, Content: "Hello 1", Author: "userA"}    post2 := &Post{Id: 2, Content: "Hello 2", Author: "userB"}    post3 := &Post{Id: 3, Content: "Hello 3", Author: "userC"}    post4 := &Post{Id: 4, Content: "Hello 4", Author: "userA"}    store(post1)    store(post2)    store(post3)    store(post4)    storeToGob(PostById, "d:/PostById.gob")    storeToGob(PostByAuthor, "d:/PostByAuthor.gob")    storeToGob(post3, "d:/post3.gob")    PostById = map[int]*Post{}    PostByAuthor = map[string][]*Post{}    var post33 *Post    load(&post33, "d:/post3.gob")    fmt.Println(post33)    load(&PostById, "d:/PostById.gob")    fmt.Println(PostById[1])    fmt.Println(PostById[2])    load(&PostByAuthor, "d:/PostByAuthor.gob")    for _, post := range PostByAuthor["userA"] {        fmt.Println(post)    }}

转载地址:http://byenl.baihongyu.com/

你可能感兴趣的文章
数据结构 ConcurrentHashMap
查看>>
spring boot 初始化是怎么扫描类的
查看>>
css3实现圆形进度条
查看>>
C++学习需要看的书籍
查看>>
jQuery的常用方法
查看>>
mysql联查时为空补全和jdbc获取最后插入生成的id
查看>>
[Android] ArcFace人脸识别 Demo
查看>>
人脸识别 闸机开发分享
查看>>
iOS开发 怎么适配iOS9
查看>>
Jquery选择器性能发现
查看>>
iptables从入门到应用
查看>>
WindowsAPI详解——TerminateProcess 终止|杀死其它进程
查看>>
java入门:dos命令运行java文件
查看>>
MySQL基本知识点
查看>>
自动加入域脚本
查看>>
黑莓10应用多源自Android
查看>>
创建Oracle表空间
查看>>
vm,vbox 虚拟机设置开机自动启动(创建虚拟机快捷方式的命令)
查看>>
用GoAccess分析Nginx的日志
查看>>
我的友情链接
查看>>