go - 编码/gob 是确定性的吗?

标签 go gob

我们能否期望两个 Go 对象 x, y 使得 x 等于 y(假设接口(interface)和映射没有技巧,只是结构和数组)gob_encode(x) 和 gob_encode(y) 的输出将始终是一样吗?

编辑(2018 年 6 月 8 日):

当涉及 map 时,gob 编码是非确定性。这是由于 map 的随机迭代顺序,导致它们的序列化顺序随机。

最佳答案

只要它“完成工作”,您就不必太在意。但电流encoding/gob实现是确定性的。但是(继续阅读)!

开始于:

A stream of gobs is self-describing. Each data item in the stream is preceded by a specification of its type, expressed in terms of a small set of predefined types.

这意味着如果您第一次对某个类型的值进行编码,则会发送类型信息。如果您对同一类型的另一个值进行编码,则不会再次传输类型描述,只是对其先前规范的引用。因此,即使您对同一个值进行两次编码,它也会产生不同的字节序列,因为第一个将包含类型规范和值,第二个将仅包含一个类型引用(例如类型 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] 序列。

但是如果你创建 2 个不同的 gob.Encoder s 并且您以相同的顺序写入相同的值,它们将产生准确的结果。

请注意,在前面的声明中“相同顺序”也很重要。因为类型规范是在发送这种类型的第一个值时传输的,所以以不同顺序发送不同类型的值也会以不同顺序传输类型规范,因此类型的引用/标识符可能不同,这意味着当值这样的类型被编码,将使用/发送不同的类型引用/id。

另请注意,gob 包的实现可能会因版本而异。这些更改将向后兼容(它们必须明确说明是否出于某种原因它们会进行向后不兼容的更改),但向后兼容并不意味着输出是相同的。所以不同的 Go 版本可能会产生不同的结果(但所有兼容版本都可以解码)。

关于go - 编码/gob 是确定性的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33228700/

相关文章:

file - 无法使用 gob 将数据正确存储在文件中

Go:通过管道发送 gob 挂起 - 更新:进程外 http.ResponseWriter 正在阻塞

go - 如何将 utc 以毫秒为单位聚类到所属的月份

go - 为什么存储在接口(interface)中的值在 Golang 中不可寻址

go - 如何在Golang中使用gob连续监听客户端

Golang 将 gob 字符串转换为接口(interface)

Golang TCPConn Gob 通信

html - beego,找不到重新定义的页面,404页面不显示html,为什么?

mongodb - 总是产生相同哈希的无序 2 字符串哈希函数

regex - 如何使用 Golang 正则表达式查找完全匹配的单词?