亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

兩個 gob 編碼器產生不同的結果

兩個 gob 編碼器產生不同的結果

Go
慕仙森 2022-10-24 08:49:22
......它讓我發瘋,試圖理解我做錯了什么!游樂場:https ://go.dev/play/p/ZQP8Y-gwihQ該示例看起來很做作,但它是從出現錯誤的代碼中提取的。在我的代碼中,我正在對字節緩沖區進行哈希處理,并希望該過程是可預測的。package mainimport (    "bytes"    "encoding/gob"    "fmt"    "log")type Foo struct {    Bar string    Baz string}func (f *Foo) X() string {    var b bytes.Buffer    s := struct {        Bar string        Baz string    }{        f.Bar,        f.Baz,    }    log.Printf("%v", s)    gob.NewEncoder(&b).Encode(s)    return fmt.Sprintf("%x", b)}func (f *Foo) Y(x string) string {    var b bytes.Buffer    s := struct {        Bar string        Baz string        S   string    }{        f.Bar,        f.Baz,        x,    }    log.Printf("%v", s)    gob.NewEncoder(&b).Encode(s)    return fmt.Sprintf("%x", b)}func main() {    a := &Foo{        Bar: "bar",        Baz: "baz",    }    log.Println(a.X())    log.Println(a.Y("something"))}運行產量:{bar baz}{1cff81030102ff820001020103426172010c00010342617a010c0000000dff820103626172010362617a00 0 0}{bar baz something}{22ff83030102ff840001030103426172010c00010342617a010c00010153010c00000018ff840103626172010362617a0109736f6d657468696e6700 0 0}注釋掉log.Println(a.X())產量:{bar baz something}{22ff81030102ff820001030103426172010c00010342617a010c00010153010c00000018ff820103626172010362617a0109736f6d657468696e6700 0 0}我希望這兩種編碼相同,但它們在我假設對應于字段邊界的位置上(可預測地)不同:22ff83 # 81030102ff84 # 820001030103426172010c00010342617a010c00010153010c00000018ff84 # 820103626172010362617a0109736f6d657468696e6700即使細節不同,行為也與我的代碼一致。我在每個方法中都創建了一個新的bytes.Bufferand gob.NewEncoder,所以不清楚為什么調用X會改變Y.
查看完整描述

1 回答

?
大話西游666

TA貢獻1817條經驗 獲得超14個贊

您缺少的是Encoder實例生成的字節流除了每個狀態之外還具有全局Encoder(程序范圍)狀態。該全局狀態由 [注意:此處編輯的短語] 注冊和發送類型組成。

當您發送一個類型化的值時,如果該類型在發送之前尚未注冊,它將在全局狀態下為您注冊。這會為該類型分配一個內部數值。見Register(及其同伴RegisterName)。當您調用您的時,它會注冊保存在 中X的匿名結構類型。當您調用您的時,它會注冊保存在 中的匿名結構類型。它們得到不同的內部類型編號。通過調用,該類型永遠不會被注冊,并且' 的類型會在第一個可用號碼下注冊。sXYsYXY

在我的代碼中,我正在對字節緩沖區進行散列...

這不是一個好主意,因為現在可能很明顯的原因。 但是,如果您以已知的順序顯式注冊每種類型,那么您在這里就足夠安全了,除非將來的某個版本出于某些(可能是好的)原因更改了線路格式。 糟糕,對此進行測試表明它也無濟于事。這是因為即使該類型已注冊,它也沒有設置傳輸編號,直到第一次對該類型的值進行編碼。因此,您需要對每種類型的值進行編碼(并且可以選擇丟棄)。

這是一個仔細丟棄編碼這兩種類型的有效示例,以便注釋掉調用對log.Println(a.X())第二個值的編碼沒有影響。


查看完整回答
反對 回復 2022-10-24
  • 1 回答
  • 0 關注
  • 143 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號