Package gob

import "encoding/gob"
Overview
Index
Examples

Overview ▾

软件包gob管理gob的流-编码器(发送器)和解码器(接收器)之间交换的二进制值. 典型的用途是传输远程过程调用(RPC)的参数和结果,例如由程序包" net / rpc"提供的参数和结果.

该实现为流中的每种数据类型编译一个自定义编解码器,当使用单个Encoder传输值流时,效率最高,这将摊销编译成本.

Basics

一滴滴水是自描述的. 流中的每个数据项之前都有其类型的规范,以一小套预定义类型表示. 指针不被传输,但是指针所指向的事物被传输. 即,将值展平. 不允许使用nil指针,因为它们没有值. 递归类型可以很好地工作,但是递归值(带有循环的数据)是有问题的. 这可能会改变.

要使用料滴,请创建一个编码器,并为它提供一系列数据项,作为值或可以取消引用值的地址. 编码器确保在需要之前发送所有类型信息. 在接收端,解码器从编码流中检索值并将其解压缩为局部变量.

Types and Values

源值和目标值/类型不必完全对应. 对于结构体,源中存在但接收变量不存在的字段(按名称标识)将被忽略. 接收变量中但传输类型或值中缺少的字段将在目标中被忽略. 如果两个字段中都存在相同名称的字段,则它们的类型必须兼容. 接收器和发送器都将进行所有必要的间接和解引用,以在料滴和实际Go值之间进行转换. 例如,gob类型是示意性的,

struct { A, B int }

可以从以下任何Go类型发送或接收:

struct { A, B int }	// the same
*struct { A, B int }	// extra indirection of the struct
struct { *A, **B int }	// extra indirection of the fields
struct { A, B int64 }	// different concrete value type; see below

It may also be received into any of these:

struct { A, B int }	// the same
struct { B, A int }	// ordering doesn't matter; matching is by name
struct { A, B, C int }	// extra field (C) ignored
struct { B int }	// missing field (A) ignored; data will be dropped
struct { B, C int }	// missing field (A) ignored; extra field (C) ignored.

Attempting to receive into these types will draw a decode error:

struct { A int; B uint }	// change of signedness for B
struct { A int; B float }	// change of type for B
struct { }			// no field names in common
struct { C, D int }		// no field names in common

整数有两种传输方式:任意精度的有符号整数或任意精度的无符号整数. gob格式不存在int8,int16等歧视; 只有有符号和无符号整数. 如下所述,发送器以可变长度编码发送该值; 接收器接受该值并将其存储在目标变量中. 浮点数始终使用IEEE-754 64位精度发送(请参见下文).

可以将带符号的整数接收到任何带符号的整数变量中:int,int16等; 无符号整数可以被接收到任何无符号整数变量中; 浮点值可以接收到任何浮点变量中. 但是,目标变量必须能够表示该值,否则解码操作将失败.

还支持结构,数组和切片. 结构仅对导出的字段进行编码和解码. 特殊有效的表示形式支持字符串和字节数组(请参见下文). 当对条带进行解码时,如果现有条带具有容量,则条带将在适当位置扩展; 如果不是,则分配一个新的数组. 无论如何,所得切片的长度报告已解码元素的数量.

通常,如果需要分配,则解码器将分配内存. 如果没有,它将使用从流中读取的值更新目标变量. 它不会首先对其进行初始化,因此,如果目标是复合值(例如映射,结构或切片),则解码后的值将逐元素合并到现有变量中.

功能和频道将不会通过gob发送. 尝试在顶级对此类值进行编码将失败. chan或func类型的struct字段与未导出的字段完全一样,将被忽略.

Gob可以编码任何实现GobEncoder或encoding.BinaryMarshaler接口的类型的值,方法是按优先级顺序调用相应的方法.

Gob可以通过调用相应的方法(同样按照优先顺序)来解码实现GobDecoder或encoding.BinaryUnmarshaler接口的任何类型的值.

Encoding Details

本节介绍了编码,这些细节对于大多数用户而言并不重要. 详细信息自下而上呈现.

发送无符号整数是以下两种方式之一. 如果小于128,则以该值作为字节发送. 否则,它将作为保存该值的最小长度的big-endian(高字节在前)字节流发送,之后是一个保存字节数的字节,取反. 因此,将0发送为(00),将7发送为(07),将256发送为(FE 01 00).

布尔值以无符号整数进行编码:0表示false,1表示true.

有符号整数i编码在无符号整数u中. 在u中,第1位向上包含该值; 位0表示是否应在收到后对其进行补充. 编码算法如下所示:

var u uint
if i < 0 {
	u = (^uint(i) << 1) | 1 // complement i, bit 0 is 1
} else {
	u = (uint(i) << 1) // do not complement i, bit 0 is 0
}
encodeUnsigned(u)

因此,低位类似于符号位,但是使它成为补码位可以保证最大的负整数不是特殊情况. 例如,-129 = ^ 128 =(^ 256 >> 1)编码为(FE 01 01).

浮点数始终作为float64值的表示形式发送. 使用math.Float64bits将该值转换为uint64. 然后,将uint64字节反转并作为常规的无符号整数发送. 字节反转意味着尾数的指数和高精度部分排在第一位. 由于低位通常为零,因此可以节省编码字节. 例如,17.0仅编码为三个字节(FE 31 40).

字符串和字节片作为无符号计数发送,后跟该值的许多未解释字节.

所有其他切片和数组将以无符号计数形式发送,然后使用标准gob编码为其类型依次递归许多元素.

映射以无符号计数形式发送,后跟那么多键,元素对. 空的但非零的映射将被发送,因此,如果接收者尚未分配一个,则除非已发送的映射为零且不在最高级别,否则始终将在接收时分配一个.

在切片和数组以及映射中,即使所有元素均为零,也将传输所有元素,即使是零值元素.

结构以(字段编号,字段值)对的序列发送. 字段值使用其类型的标准gob编码递归发送. 如果字段的类型值为零(数组除外;请参见上文),则将其从传输中省略. 字段编号由编码结构的类型定义:编码类型的第一个字段为字段0,第二个字段为字段1,依此类推.在对值进行编码时,为提高效率而对字段编号进行了增量编码,并且字段始终以增加字段数的顺序发送; 因此,增量没有符号. 增量编码的初始化将字段号设置为-1,因此将以无符号增量= 1,无符号值= 7或(01 07)的形式发送具有值7的无符号整数字段0. 最后,在所有字段都已发送后,终止标记表示该结构的结尾. 该标记是delta = 0值,具有表示(00).

不检查接口类型的兼容性; 为了进行传输,所有接口类型都被视为单个"接口"类型的成员,类似于int或[] byte-实际上,它们都被视为interface {}. 接口值以字符串的形式发送,该字符串标识要发送的具体类型(必须通过调用Register预先定义的名称),然后是后续数据长度的字节计数(因此,如果不能存储),然后对接口值中存储的具体(动态)值进行常规编码. (零接口值由空字符串标识,不传输任何值.)接收到解码器后,解码器将验证解包的混凝土项是否满足接收变量的接口.

如果将值传递给Encode且类型不是结构(或指向结构的指针等),则为简化处理,将其表示为一个字段的结构. 唯一可见的效果是对值之后的零字节进行编码,就像在已编码结构的最后一个字段之后一样,以便解码算法知道顶级值何时完成.

类型的表示在下面描述. 在编码器和解码器之间的给定连接上定义类型时,将为其分配带符号的整数类型id. 调用Encoder.Encode(v)时,请确保为v的类型及其所有元素分配了一个id,然后发送对(typeid,encoded-v),其中typeid是已编码类型的类型id v的编码和-v是值v的gob编码.

为了定义类型,编码器选择一个未使用的正类型id并发送对(-type id,encoded-type),其中encoding-type是wireType描述的gob编码,由以下类型构成:

type wireType struct {
	ArrayT           *ArrayType
	SliceT           *SliceType
	StructT          *StructType
	MapT             *MapType
	GobEncoderT      *gobEncoderType
	BinaryMarshalerT *gobEncoderType
	TextMarshalerT   *gobEncoderType

}
type arrayType struct {
	CommonType
	Elem typeId
	Len  int
}
type CommonType struct {
	Name string // the name of the struct type
	Id  int    // the id of the type, repeated so it's inside the type
}
type sliceType struct {
	CommonType
	Elem typeId
}
type structType struct {
	CommonType
	Field []*fieldType // the fields of the struct.
}
type fieldType struct {
	Name string // the name of the field.
	Id   int    // the type id of the field, which must be already defined
}
type mapType struct {
	CommonType
	Key  typeId
	Elem typeId
}
type gobEncoderType struct {
	CommonType
}

如果存在嵌套的类型ID,则必须先定义所有内部类型ID的类型,然后再使用顶级类型ID描述已编码的v.

为了简化设置,定义了连接以先验了解这些类型,以及基本的gob类型int,uint等.它们的ID为:

bool        1
int         2
uint        3
float       4
[]byte      5
string      6
complex     7
interface   8
// gap for reserved ids.
WireType    16
ArrayType   17
CommonType  18
SliceType   19
StructType  20
FieldType   21
// 22 is slice of fieldType.
MapType     23

最后,通过调用Encode创建的每条消息均以消息中剩余字节数的编码无符号整数计数开头. 在初始类型名称之后,接口值以相同的方式包装; 实际上,接口值的作用类似于对Encode的递归调用.

总而言之,gob流看起来像

(byteCount (-type id, encoding of a wireType)* (type id, encoding of a value))*

其中*表示零个或多个重复,并且值的类型ID必须预定义或在流中的值之前定义.

兼容性:对该程序包进行的任何将来更改都将努力保持与使用以前版本编码的流的兼容性. 也就是说,此软件包的任何发行版本都应能够解码以任何先前发行版本写入的数据,但要考虑到诸如安全修复程序之类的问题. 有关背景信息,请参见Go兼容性文档: https : //golang.org/doc/go1compat

See "Gobs of data" for a design discussion of the gob wire format: https://blog.golang.org/gobs-of-data

示例(基本)

此示例显示了包的基本用法:创建编码器,传输一些值,并通过解码器接收它们.

"Pythagoras": {3, 4}
"Treehouse": {1782, 1841}

示例(EncodeDecode)

本示例传输一个实现自定义编码和解码方法的值.

{3 4 5}

示例(接口)

本示例说明如何对接口值进行编码. 与常规类型的主要区别是注册实现接口的具体类型.

5
10
15

func Register

func Register(value interface{})

寄存器在其内部类型名称下记录由该类型的值标识的类型. 该名称将标识作为接口变量发送或接收的值的具体类型. 仅将要注册的类型将作为接口值的实现进行注册. 期望仅在初始化期间使用,如果类型和名称之间的映射不是双射,它会感到恐慌.

func RegisterName

func RegisterName(name string, value interface{})

RegisterName类似于Register,但是使用提供的名称而不是类型的默认名称.

type CommonType

CommonType保存所有类型的元素. 它是一个历史工件,为保持二进制兼容性而保留,并且仅出于包对类型描述符的编码的目的而导出. 它不适用于客户直接使用.

type CommonType struct {
    Name string
    Id   typeId
}

type Decoder

解码器管理从连接的远程侧读取的类型和数据信息的接收. 对于多个goroutine并发使用是安全的.

解码器仅对解码后的输入大小进行基本的完整性检查,并且其限制不可配置. 解码来自不受信任来源的gob数据时请务必小心.

type Decoder struct {
    // contains filtered or unexported fields
}

func NewDecoder

func NewDecoder(r io.Reader) *Decoder

NewDecoder返回一个新的解码器,该解码器从io.Reader中读取. 如果r还没有实现io.ByteReader,它将包装在bufio.Reader中.

func (*Decoder) Decode

func (dec *Decoder) Decode(e interface{}) error

解码从输入流中读取下一个值,并将其存储在由空接口值表示的数据中. 如果e为nil,则该值将被丢弃. 否则,e底下的值必须是指向接收到的下一个数据项的正确类型的指针. 如果输入位于EOF,则Decode返回io.EOF,并且不修改e.

func (*Decoder) DecodeValue

func (dec *Decoder) DecodeValue(v reflect.Value) error

DecodeValue从输入流中读取下一个值. 如果v为零reflect.Value(v.Kind()==无效),则DecodeValue丢弃该值. 否则,它将值存储到v中.在这种情况下,v必须表示数据的非空指针或为可分配的reflect.Value(v.CanSet())如果输入为EOF,则DecodeValue返回io.EOF和不修改v

type Encoder

编码器管理类型和数据信息到连接另一端的传输. 对于多个goroutine并发使用是安全的.

type Encoder struct {
    // contains filtered or unexported fields
}

func NewEncoder

func NewEncoder(w io.Writer) *Encoder

NewEncoder返回一个新的编码器,它将在io.Writer上传输.

func (*Encoder) Encode

func (enc *Encoder) Encode(e interface{}) error

编码发送由空接口值表示的数据项,从而确保所有必需的类型信息都已首先发送. 将nil指针传递给Encoder会感到恐慌,因为它们无法通过gob传输.

func (*Encoder) EncodeValue

func (enc *Encoder) EncodeValue(value reflect.Value) error

EncodeValue传输由反射值表示的数据项,从而确保所有必需的类型信息均已首先传输. 将nil指针传递给EncodeValue会感到恐慌,因为它们无法通过gob传输.

type GobDecoder

GobDecoder是描述数据的接口,该接口提供了自己的例程,用于解码GobEncoder发送的传输值.

type GobDecoder interface {
    // GobDecode overwrites the receiver, which must be a pointer,
    // with the value represented by the byte slice, which was written
    // by GobEncode, usually for the same concrete type.
    GobDecode([]byte) error
}

type GobEncoder

GobEncoder是描述数据的接口,该接口提供自己的表示形式,用于编码值以传输到GobDecoder. 实现GobEncoder和GobDecoder的类型可以完全控制其数据的表示形式,因此可以包含诸如私有字段,通道和函数之类的东西,这些通常在gob流中是不可传输的.

注意:由于gob可以永久存储,因此最好的设计是确保GobEncoder使用的编码随软件的发展而稳定. 例如,对于GobEncode在编码中包含版本号可能很有意义.

type GobEncoder interface {
    // GobEncode returns a byte slice representing the encoding of the
    // receiver for transmission to a GobDecoder, usually of the same
    // concrete type.
    GobEncode() ([]byte, error)
}

by  ICOPY.SITE