序列化持久存储gob

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

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

gob包的用法很简单,但有必要去了解它的背景知识,见官方手册:https://golang.org/pkg/encoding/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 *Post
load(&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 main

import (
"bytes"
"encoding/gob"
"fmt"
"io/ioutil"
) type Post struct {
Id int
Content string
Author string
} var PostById map[int]*Post
var PostByAuthor map[string][]*Post func 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)
}
}

Go Web:数据存储(3)——gob对象序列化的更多相关文章

  1. Android中数据的传递以及对象序列化

    Android中当两个Activity需要有信息交互的时候,可以使用Intent.具体来说: 发送单一类型数据: 发送方: String data = "Hello SecondActivi ...

  2. Web 数据存储总结

    随着Web应用程序的出现,也产生了对于能够在客户端上存储用户信息能力的要求.这个问题的第一个解决方案是以cookie形似出现的.网景公司在一份名为“Persistent Client State: H ...

  3. 浅析Web数据存储-Cookie、UserData、SessionStorage、WebSqlDatabase

    Cookie 它是标准的客户端浏览器状态保存方式,可能在浏览器诞生不久就有Cookie了,为什么需要Cookie 这个东东?由于HTTP协议没有状态,所以需要一个标志/存储来记录客户浏览器当前的状态, ...

  4. [MISS静IOS开发原创文摘]-AppDelegate存储全局变量和 NSUserDefaults standardUserDefaults 通过模型保存和读取数据,存储自定义的对象

    由于app开发的需求,需要从api接口获得json格式数据并保存临时的 app的主题颜色 和 相关url 方案有很多种: 1, 通过AppDelegate保存为全局变量,再获取 2,使用NSUSerD ...

  5. web数据存储

    数据的存储必然是任何网站必须经历的事,我们可以将数据存放在不同地方,数据库.文件.内存.程序本身.cookie,session中都可以,但是只要需要持久化保留的数据,那么最终肯定还是落在磁盘之上的,我 ...

  6. 使用MapReduce读取HBase数据存储到MySQL

    Mapper读取HBase数据 package MapReduce; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hba ...

  7. 数据存储之Web存储(sessionStorage localStorage globalStorage )

    Web Storage 两个目标 提供一种在cookie之外的存储会话守数据的途径 提供一种存储大量可以跨会话存在的数据机制 最初的Web Storage规范包含两个对象 sessionStorage ...

  8. iOS数据存储之对象归档

    iOS数据存储之对象归档 对象归档 对象归档是iOS中数据持久化的一种方式. 归档是指另一种形式的序列化,但它是任何对象都可以实现的更常规的类型.使用对模型对象进行归档的技术可以轻松将复杂的对象写入文 ...

  9. 一个web应用的诞生--数据存储

    上一章实现了登录的部分功能,之所以说是部分功能,是因为用户名和密码写成固定值肯定是不可以的,一个整体的功能,至少需要注册,登录,密码修改等,这就需要提供一个把这些值存储到数据库的能力. 当前的主流数据 ...

随机推荐

  1. [Solution] JZOJ-5818 做运动

    [Solution] JZOJ-5818 做运动 Time Limits:2000ms Memory Limits:524288KB Description 一天,Y 君在测量体重的时候惊讶的发现,由 ...

  2. U-Boot Makefile分析(4)具体子Makefile的分析

    前面分析的都是多数Makefile要读入的文件,这次我们以drivers/mtd/nand/Makefile为例,分析一个具体的子Makefile是如何工作的. 子Makefile的结构是固定的: i ...

  3. Eclipse的application.properties文件输出中文成unicode编码

    今天添application.properties时,无法输入中文,输入的中文直接变成了unicode的编码形式.原因是Eclipse的Spring Properties文件的默认编码为iso-885 ...

  4. php Glob() 使用 查找文件:

    1. 取得所有的后缀为PHP的文件(加上路径)$file=glob('D:/phpStudy/WWW/prictue/*.php');print_r($file);//如果没有指定文件夹的话就是显示出 ...

  5. Exp4 恶意代码分析 ——20164325王晓蕊

    1.实践目标 监控你自己系统的运行状态,看有没有可疑的程序在运行. 分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使用原生指令或sysinternals,systracer套件 ...

  6. spring 读取yaml配置文件

    从Spring框架4.1.0增加了对YAML的支持,Spring框架4.1.0 maven POM具有Snakeyaml依赖性  . 您可以在Spring Boot应用中使用两种方式加载YAML: 1 ...

  7. vs链接错误解决方法

    常见引起链接错误的主要原因是由于项目不能找到所需的动态库的路径: 这里介绍一下引用第三方动态库的配置方法: 方法一: vs加载动态库需要先把动态库拷贝到exe所在文件夹,再修改项目属性: 链接器-&g ...

  8. Oneinstack 环境安装 Flarum 轻量级论坛程序

    之前做了个论坛,使用的是discuz框架,虽然这个框架已经很成熟,功能也相对较多,但毕竟老框架了,今天尝试用Flarum来搭建一个论坛,Flarum相对来说美观而且速度快 系统环境使用oneinsta ...

  9. Javascript高级编程学习笔记(51)—— DOM2和DOM3(3)操作样式表

    操作样式表 在JS中样式表用一种类型来表示,以便我们在JS对其进行操作 这一类型就是CSSStyleSheet 即CSS样式表类型,包括了之前 style 对象所不包括的外部样式表以及嵌入样式表 其中 ...

  10. Javascript高级编程学习笔记(34)—— 客户端检测(3)用户代理检测

    用户代理检测 前面的文章介绍的是如何检测浏览器对某一功能的支持情况 但是在实践中我们有些时候免不了需要知道用户到底是用的什么浏览器对我们的站点进行访问 这也是统计用户行为的一部分 用户代理检测这种方式 ...