3 回答

TA貢獻1842條經驗 獲得超13個贊
只要它“完成工作”,您就不應該真正在意。但是當前的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())
輸出(在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.Encoders 并以相同的順序寫入相同的值,它們將產生精確的結果。
請注意,在前面的語句中“相同順序”也很重要。因為類型說明是在發送這種類型的第一個值時傳輸的,所以不同類型的值以不同的順序發送也會以不同的順序傳輸類型說明,因此類型的引用/標識符可能不同,這意味著當一個值此類類型已編碼,將使用/發送不同類型的引用/ID。
另請注意,gob包的實現可能會因發行版而異。這些更改將向后兼容(他們必須明確說明是否出于某種原因會進行向后不兼容的更改),但向后兼容并不意味著輸出是相同的。所以不同的 Go 版本可能會產生不同的結果(但所有兼容版本都可以解碼)。

TA貢獻1877條經驗 獲得超6個贊
可能應該注意的是,接受的答案是不正確的:編碼/gob 不會以確定性的方式對地圖元素進行排序:https : //play.golang.org/p/Hh3_5Kb3Znn
我已經分叉了 encoding/gob 并添加了一些代碼以在將它們寫入流之前按鍵對地圖進行排序。這會影響性能,但我的特定應用程序不需要高性能。請記住自定義封送拆收器可以打破這一點,所以小心使用:https : //github.com/dave/stablegob

TA貢獻1998條經驗 獲得超6個贊
如果您使用不同的類型和不同的編碼器,它也不是確定性的。
例子:
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))
}
在Go Playground 中奔跑
請注意,如果你注釋掉encint()或者encint64()在encstring會產生不同的字節和不同的哈希碼。
盡管使用了不同的對象/指針,但還是會發生這種情況。
- 3 回答
- 0 關注
- 260 瀏覽
添加回答
舉報