我们是否可以期望两个Go对象x,y等于x(假设接口和映射没有技巧性,仅是结构和数组),那么gob_encode(x)和gob_encode(y)的输出将始终相同?
编辑(2018年6月8日):
当涉及 地图* 时,gob编码是 不确定的 。这是由于映射的随机迭代顺序,导致其序列化被随机排序。 *
只要它“完成工作”,您就不需要真正关心。但是当前的encoding/gob实现是确定性的。但是(继续阅读)!
encoding/gob
以来:
一滴滴水是自我描述的。流中的每个数据项之前都有其类型的规范,以一小套预定义类型表示。
这意味着如果您第一次编码类型的值,则将发送类型信息。如果您对另一个相同类型的值进行编码,则不会再次传输类型描述,而仅是对其先前规范的引用。因此,即使您对相同的值进行两次编码,也会产生不同的字节序列,因为第一个包含类型spec和值,第二个仅包含类型ref(例如,类型id)和值。
请参阅以下示例:
type Int struct{ X int } b := &bytes.Buffer{} e := gob.NewEncoder(b) e.Encode(Int{1}) fmt.Println(b.Bytes()) e.Encode(Int{1}) fmt.Println(b.Bytes()) e.Encode(Int{1}) fmt.Println(b.Bytes())
输出(在Go Playground上尝试):
[23 255 129 3 1 1 3 73 110 116 1 255 130 0 1 1 1 1 88 1 4 0 0 0 5 255 130 1 2 0] [23 255 129 3 1 1 3 73 110 116 1 255 130 0 1 1 1 1 88 1 4 0 0 0 5 255 130 1 2 0 5 255 130 1 2 0] [23 255 129 3 1 1 3 73 110 116 1 255 130 0 1 1 1 1 88 1 4 0 0 0 5 255 130 1 2 0 5 255 130 1 2 0 5 255 130 1 2 0]
如图所示,第一个调用会Encode()生成大量字节,再加上我们的Int值[5 255 130 1 2 0],第二个和第三个调用会添加相同的[5 255 130 1 2 0]序列。
Encode()
Int
[5 255 130 1 2 0]
但是,如果创建2个不同的gob.Encoders,并且以相同的顺序写入相同的值,则它们将产生精确的结果。
gob.Encoder
注意,在前面的语句中“相同的顺序”也很重要。因为类型规范是在发送该类型的第一个值时发送的,所以以不同顺序发送不同类型的值也会以不同顺序发送类型规范,因此类型的引用/标识符可能会有所不同,这意味着当此类类型已编码,将使用/发送不同的类型引用/ id。
还要注意,该gob软件包的实现可能因发行版本而异。这些更改将向后兼容(如果出于某种原因它们将进行向后不兼容的更改,则必须明确声明),但是向后兼容并不意味着输出是相同的。因此,不同的Go版本可能会产生不同的结果(但是所有兼容版本都可以解码)。
gob