对于两个Go对象x,y,使得x等于y(假设不存在接口和映射的复杂性,只是结构和数组),那么gob_encode(x)和gob_encode(y)的输出总是相同的吗?
编辑(2018年6月8日):
当涉及到non-deterministic映射时,gob编码是。这是由于映射的随机迭代顺序,导致它们的序列化被随机排序。
发布于 2015-10-20 05:45:32
你不应该真的关心它,只要它“完成工作”。但是当前的encoding/gob实现是确定性的。但是(继续读)!
因为:
一股采空区是自我描述的。流中的每个数据项前面都有其类型的规范,表示为一组预定义的类型。
这意味着,如果您第一次编码一个类型的值,类型信息将被发送。如果对同一类型的另一个值进行编码,类型说明将不再传输,只是对其先前规范的引用。因此,即使对相同的值编码两次,它也会产生不同的字节序列,因为第一个字节序列将包含类型规范和值,第二个字节序列将只包含类型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())输出(在围棋游乐场上尝试):
[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]序列。
但是,如果您创建了两个不同的gob.Encoder,并且按照相同的顺序编写相同的值,它们将产生精确的结果。
注意,在前面的语句中,“相同的顺序”也很重要。由于在发送该类型的第一个值时发送类型规范,以不同顺序发送不同类型的值也将以不同的顺序发送类型规格,因此类型的引用/标识符可能有所不同,这意味着当对该类型的值进行编码时,将使用/发送不同类型的引用/id。
还要注意的是,gob包的实现可能会在不同版本之间发生变化。这些更改将是向后兼容的(如果出于某种原因,它们必须显式声明是否会进行向后不兼容的更改),但向后兼容并不意味着输出是相同的。因此,不同的Go版本可能会产生不同的结果(但是所有版本都是可解码的,所有兼容版本都是可解码的)。
发布于 2018-06-07 04:59:02
应该注意的是,接受的答案是不正确的:编码/gob不以确定的方式排列map元素:5Kb3Znn
在将映射写入流之前,我对编码/gob进行了分叉处理,并添加了一些代码来按键对映射进行排序。这将影响性能,但我的特定应用程序不需要高性能。请记住,自定义编组程序可能会破坏这一点,因此请小心使用:https://github.com/dave/stablegob
发布于 2020-10-26 11:23:51
如果您使用不同的类型和不同的编码器,它也不是确定性的。
示例:
package main
import (
"bytes"
"crypto/sha1"
"encoding/gob"
"encoding/hex"
"log"
)
func main() {
encint()
encint64()
encstring()
}
func encint() {
s1 := []int{0, 2, 4, 5, 7}
buf2 := bytes.Buffer{}
enc2 := gob.NewEncoder(&buf2)
enc2.Encode(s1)
}
func encint64() {
s1 := []int64{0, 2, 4, 5, 7}
buf2 := bytes.Buffer{}
enc2 := gob.NewEncoder(&buf2)
enc2.Encode(s1)
}
func encstring() {
s1 := []string{"a", "b", "c", "d"}
buf2 := bytes.Buffer{}
enc2 := gob.NewEncoder(&buf2)
enc2.Encode(s1)
log.Println(buf2.Bytes())
hash := sha1.New()
hash.Write(buf2.Bytes())
ret := hash.Sum(nil)
log.Println(hex.EncodeToString(ret))
}在围棋游乐场中运行
注意,如果您注释掉encint()或encint64(),encstring将生成不同的字节和不同的哈希代码。
尽管使用了不同的对象/指针,但还是会发生这种情况。
https://stackoverflow.com/questions/33228700
复制相似问题