gob包("encoding/gob")管理gob流——在encoder(编码器,也就是发送器)和decoder(解码器,也就是接受器)之间交换的字节流数据(gob 就是 go binary的缩写)。一般用于传递远端程序调用(RPC)的参数和结果。

要使用gob,通过调用NewEncoder()方法先创建一个编码器,并向其提供一系列数据;然后在接收端,通过调用NewDecoder()方法创建一个解码器,它从数据流中恢复数据并将它们填写进本地变量里。下面会通过几个例子进行说明。

发送端和接收端的值/类型不需要严格匹配。对结构体来说,某一字段(通过字段名进行识别)如果发送端有而接收端没有,会被忽略;接收端有而发送端没有的字段也会被忽略;发送端和接收端都有的字段其类型必须是可兼容的;发送端和接收端都会在gob流和实际go类型之间进行必要的指针取址/寻址工作。举例如下:

下面是发送端的承载数据的结构体:
struct { A, B int }
可以和如下类型互相发送和接收:
struct { A, B int } // 同一类型
*struct { A, B int } // 结构体需要额外重定向(指针)
struct { *A, **B int } // 字段需要额外重定向(指针)
struct { A, B int64 } // 同为整型/浮点型且符号类型相同的不同值类型 可以发送给如下任一类型:
struct { A, B int } // 同一类型
struct { B, A int } // 字段顺序改变无影响,按名称匹配
struct { A, B, C int } // 忽略多出的字段C
struct { B int } // 忽略缺少的字段A,会丢弃A的值
struct { B, C int } // 忽略缺少的字段A,忽略多出的字段C 但尝试发送给如下类型的话就会导致错误:
struct { A int; B uint } // B字段改变了符号类型
struct { A int; B float } // B字段改变了类型
struct { } // 无共同字段名
struct { C, D int } // 无共同字段名

首先来看一个关于encode/decode结构体数据类型的示例。仔细观察这个例子,有助理解上面所说的发送端和接收端之间字段匹配的问题。

type P struct {
X, Y, Z int
Name string
} type Q struct {
X, Y *int32
Name string
} type R struct {
Y, W int
} // This example shows the basic usage of the package: Create an encoder,
// transmit some values, receive them with a decoder.
func GobBasic() {
// 初始化 encoder 和 decoder
var buf bytes.Buffer
encoder := gob.NewEncoder(&buf) // will write to buf
decoder := gob.NewDecoder(&buf) // will read from buf // Encode (send) some values
err := encoder.Encode(P{X: , Y: , Z: , Name: "hello"})
if err != nil {
log.Fatal("Encode error:",err)
}
  
// case 1
// Decode (receive) and print the values
//var q Q
//err = decoder.Decode(&q)
//if err != nil {
// log.Fatal("Decode error:",err)
//}
//
//// 注意,不能写成 q.X,因为在接收方,定义的是 int型 指针
//// *(q.X) 与 *q.Y 结果相同,但前者语义更加明确
//fmt.Printf("%d %d %s\n", *(q.X), *q.Y, q.Name) //case 2
//var p P
//err = decoder.Decode(&p)
//if err != nil {
// log.Fatal("Decode error:",err)
//}
//// 这里的接收方和传入方格式完全一致
//fmt.Printf("%d %d %d %s\n", p.X, p.Y, p.Z, p.Name)

   // case 3
var r R
err = decoder.Decode(&r)
if err != nil {
log.Fatal("Decode error:",err)
} //fmt.Printf("%d %d %d %s\n", r.X, r.Y, r.Z, r.Name)
// 会输出如下:因为接收端是根据字段名称进行匹配的
// r.X undefined (type R has no field or method X)
// r.Z undefined (type R has no field or method Z)
// r.Name undefined (type R has no field or method Name)
fmt.Printf("%d\n", r.Y) // ok
}

接着我们看一下encode/decode 接口类型的值是如何操作的。与其他常规的类型(比如结构体)最大的不同在于:需要注册一个明确的实现该接口的类型。

示例如下:

type Point struct {
X, Y int
}
func (p Point) Hypotenuse() float64 {
// Hypot returns Sqrt(p*p + q*q)
return math.Hypot(float64(p.X), float64(p.Y))
}
type Pythagoras interface {
Hypotenuse() float64
} // 这个例子展示了如何 encode/decode 一个接口类型(interface{})的值
// 与其他常规的类型(比如结构体)最大的不同在于:
// 需要注册一个明确的实现该接口的类型
func GobInterface() {
// 我们必须要对encoder和decoder注册具体的类型,
// 因为通常来说,decoder和encoder是在不同的机器上的。
// 经过“注册”,解析引擎才能知道实现这一接口的具体类型是什么
// (因为同一个接口可以有多种不同的实现)
gob.Register(Point{}) p1 := Point{X: , Y: }
fmt.Println(p1.Hypotenuse()) // 5
// 编码,再解码,观察解码后返回的结果是否一致
b, _ := encode(p1)
p2, _ := decode(b)
fmt.Println(p2.Hypotenuse()) //
} // 编码,把结构体数据编码成字节流数据
func encode(p Pythagoras) ([]byte, error) {
var buf bytes.Buffer
encoder := gob.NewEncoder(&buf) // 构造编码器,并把数据写进buf中
if err := encoder.Encode(&p); err != nil {
log.Printf("encode error: %v\n", err)
return nil, err
}
return buf.Bytes(), nil
} // 解码,把字节流数据解析成结构体数据
func decode(b []byte) (Pythagoras, error) {
//var buf bytes.Buffer
bufPtr := bytes.NewBuffer(b) // 返回的类型是 *Buffer,而不是 Buffer。注意一下
decoder := gob.NewDecoder(bufPtr) // 从 bufPtr 中获取数据
var p Pythagoras
if err := decoder.Decode(&p); err != nil { // 将数据写进变量 p 中
return Point{}, err
}
return p, nil
}

Go之gob包的使用的更多相关文章

  1. golang中的rpc包用法

    RPC,即 Remote Procedure Call(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样. 我所在公司的项目是采用基于Restful的微服务架构,随着微服 ...

  2. Go Web:数据存储(3)——gob对象序列化

    序列化持久存储gob 1.内存存储 2.CSV文件存储 3.gob序列化存储 本篇文章仍然接前面的文章:内存存储,主要介绍将博客文章数据序列化持久到文件中. encoding/gob包用于编码器和解码 ...

  3. 转: gob编解码

    要让数据对象能在网络上传输或存储,我们需要进行编码和解码.现在比较流行的编码方式有JSON,XML等.然而,Go在gob包中为我们提供了另一种方式,该方式编解码效率高于JSON.gob是Golang包 ...

  4. Go语言的序列化与反序列化(gob)

    encoding/gob包实现了高效的序列化,特别是数据结构较复杂的,结构体.数组和切片都被支持. 实现代码如下://定义一个结构体type Student struct { Name string ...

  5. golang——net/rpc包学习

    1.rpc包 rpc包提供了通过网络或其他I/O连接对一个对象的导出方法的访问. 只有满足如下标准的方法才能用于远程访问,其余方法会被忽略: (1)方法是导出的(2)方法有两个参数,都是导出类型或内建 ...

  6. golang开发缓存组件

    代码地址github:cache 花了一天时间看了下实验楼的cache组件,使用golang编写的,收获还是蛮多的,缓存组件的设计其实挺简单的,主要思路或者设计点如下: 全局struct对象:用来做缓 ...

  7. [Golang]Go Packages

    ---------------------------------------------------------------------------------------------------- ...

  8. go语言入门

    Go语言最主要的特性: 自动垃圾回收 更丰富的内置类型 函数多返回值 错误处理 匿名函数和闭包 类型和接口 并发编程 反射 语言交互性 1.2.4 错误处理Go语言引入了3个关键字用 ...

  9. Go web编程学习笔记——未完待续

    1. 1).GOPATH设置 先设置自己的GOPATH,可以在本机中运行$PATH进行查看: userdeMacBook-Pro:~ user$ $GOPATH -bash: /Users/user/ ...

随机推荐

  1. 测试使用API

    https://api.github.com/users/github 返回值中的某些URL也可以作为测试API使用

  2. MongoDB 副本集的常用操作及原理

    本文是对MongoDB副本集常用操作的一个汇总,同时也穿插着介绍了操作背后的原理及注意点. 结合之前的文章:MongoDB副本集的搭建,大家可以在较短的时间内熟悉MongoDB的搭建和管理. 下面的操 ...

  3. Other-Website-Contents.md

    title: 本站目录 categories: Other sticky: 10 toc: true keywords: 机器学习基础 深度学习基础 人工智能数学知识 机器学习入门 date: 999 ...

  4. 实验1C语言开发环境使用和数据类型、运算符、表达式

    # include <stdio.h> int main() { char ch; printf("输入一个字符:\n"); scanf("%c", ...

  5. python 列表 【基本使用功能】

    #!/usr/bin/python # -*- coding: UTF-8 -*- # by Mercury_Lc list1 = list # 开个新的列表的方法 list2 = [] list1 ...

  6. P1065 作业调度方案——小模怡情,大模伤身

    P1065 作业调度方案 一个有点费手的“小”%%拟: 题都差点没读明白……: 每个机器所能完成的工序是不一样的: 每个物品完成工序的机器是指定的: 按照题面说的按时间轴推下去就行了: 没有时间上界有 ...

  7. Pytest从测试类外为测试用例动态注入数据

    今天Nelly问我Pytest能不能支持从TestClass类外传入参数?从类外批量传入各个test方法需要的参数.因为数据文件可能有很多情况,不方便依次匹配. 然而又必须用类对用例进行归类及复用,数 ...

  8. [bzoj 1010][HNOI 2008]玩具装箱

    传送门 Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压 缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号 ...

  9. codeforces#1249F. Maximum Weight Subset(树上dp)

    题目链接: http://codeforces.com/contest/1249/problem/F 题意: 一棵树的每个节点有个权值,选择一个节点集,使得任意点对的距离大于$k$ 求最大节点集权值, ...

  10. centos7 安装anaconda3

    在学习Python的时候,如果学习python3的版本,那么需要重新安装pytho3,因为系统默认的Python版本是python2,当然,有的可能需要同时保留两个版本,这里来试着使用一下anacon ...