我们可以期望两个Go对象x,y使得x等于y(假设没有接口和映射,只是结构和数组的技巧)gob_encode(x)和gob_encode(y)的输出将始终相同吗?
编辑(2018年6月8日):
当涉及地图时,gob编码是不确定的.这是由于地图的随机迭代顺序,导致它们的序列化是随机排序的.
只要它"完成工作",你就不应该真正关心.但目前的encoding/gob实施是确定性的.但是(继续阅读)!
以来:
gobs流是自我描述的.流中的每个数据项前面都有一个类型的规范,用一小组预定义类型表示.
这意味着如果您是第一次对类型的值进行编码,则将发送类型信息.如果您对另一个相同类型的值进行编码,则不会再次传输类型描述,只是对其先前规范的引用.因此,即使您将相同的值编码两次,它也会产生不同的字节序列,因为第一个将包含类型规范和值,第二个将仅包含类型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())
Run Code Online (Sandbox Code Playgroud)
输出(在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]
Run Code Online (Sandbox Code Playgroud)
如图所示,第一个Encode()生成大量字节加上我们的Int值的值[5 255 130 1 2 0],第二个和第三个调用添加相同的[5 255 130 1 2 0]序列.
但是如果你创建2个不同的gob.Encoders并且你以相同的顺序写相同的值,它们将产生精确的结果.
请注意,在之前的声明中,"相同顺序"也很重要.因为在发送这种类型的第一个值时发送类型规范,所以以不同顺序发送不同类型的值也将以不同的顺序发送类型规范,因此类型的引用/标识符可能不同,这意味着当值为0时对这种类型进行编码,将使用/发送不同类型的引用/ id.
另请注意,gob程序包的实现可能会在发行版之间发生变化.这些更改将向后兼容(如果由于某种原因,它们必须明确说明它们会进行向后不兼容的更改),但向后兼容并不意味着输出是相同的.因此,不同的Go版本可能会产生不同的结果(但所有兼容版本都可以解码).