第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

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

包裝gob解碼器

包裝gob解碼器

Go
收到一只叮咚 2022-10-24 10:00:36
我將加密的 gobs 存儲在 kv 數(shù)據(jù)庫中,并希望在帶有密鑰和接口的包中具有便利功能,它解密存儲的值,將其解碼為傳遞的接口,并且消費者代碼可以在沒有了解有關正在存儲的數(shù)據(jù)的任何信息。當它與 json 編碼器一起工作時,我無法弄清楚為什么我無法使用 gob 寫入指針值。簡化后的代碼如下所示:type Foo struct {    A string    B string}func marshal(i interface{}) ([]byte, error) {    var indexBuffer bytes.Buffer    encoder := gob.NewEncoder(&indexBuffer)    err := encoder.Encode(&i)    return indexBuffer.Bytes(), err}func unmarshal(data []byte, e interface{}) error {    buf := bytes.NewBuffer(data)    dec := gob.NewDecoder(buf)    err := dec.Decode(&e)    fmt.Println("Unmarshal", e)    return err}func marshalJ(i interface{}) ([]byte, error) {    return json.Marshal(i)}func unmarshalJ(data []byte, e interface{}) error {    return json.Unmarshal(data, e)}func main() {    foo := Foo{"Hello", "world!"}    gob.Register(Foo{})    data, err := marshal(foo)    fmt.Println("got", len(data), err)    var bar Foo    err = unmarshal(data, &bar)    fmt.Println("Main err", err)    fmt.Println("Main", bar)    fmt.Println("-------------------------")    data, err = marshalJ(foo)    fmt.Println("got J", len(data), err)    err = unmarshalJ(data, &bar)    fmt.Println("Main J err", err)    fmt.Println("Main J", bar)}(播放鏈接)unmarshalJ 的行為與我預期的一樣,即在 Main 中,我的 bar 變量是 foo 的副本,因為 unmarshalJ 接收到指向 bar 的指針并將其傳遞。另一方面,unmarshal 函數(shù)在本地更改了參數(shù),但并未對 Main 中的欄進行更改。gob.Decode 在內(nèi)部傳遞了 reflect.ValueOf,我一直試圖避免使用反射,所以我不太明白它的作用。我的兩個問題是:是否可以像我想要的那樣擁有一個包裝器,并像使用 json 編碼器一樣更改調(diào)用者的值?更多的獎勵問題,因為這讓我覺得我沒有完全掌握 go 中的指針:如何更改 unmarshal.e 的值,但當 unmarshal.e 是指向 Main.bar 的指針時不會更改 Main.bar?在這里讓我感到困惑的另一件事是,在 unmarshal 內(nèi)部,我必須將 &e 傳遞給 Decode ,否則它會以want struct type main.Foo; got non-struct.
查看完整描述

1 回答

?
繁花不似錦

TA貢獻1851條經(jīng)驗 獲得超4個贊

有兩個問題,第一個是你給unmarshal一個指針,然后在unmarshal自己內(nèi)部創(chuàng)建另一個指針,所以你最終會傳遞**Foo給 gob 解碼器。

第二個問題是您interface{}在函數(shù)內(nèi)獲取 'es 的指針。這會以某種方式影響數(shù)據(jù)的編碼方式。如果您將指針傳遞給函數(shù)并且不修改函數(shù)內(nèi)部的變量,那么一切正常。

固定代碼如下所示,playground 鏈接

type Foo struct {

    A string

    B string

}


func marshal(i interface{}) ([]byte, error) {

    var indexBuffer bytes.Buffer

    encoder := gob.NewEncoder(&indexBuffer)

    err := encoder.Encode(i)

    return indexBuffer.Bytes(), err

}


func unmarshal(data []byte, e interface{}) error {

    buf := bytes.NewBuffer(data)

    dec := gob.NewDecoder(buf)

    err := dec.Decode(e)

    fmt.Println("Unmarshal", e)

    return err

}


func marshalJ(i interface{}) ([]byte, error) {

    return json.Marshal(i)

}


func unmarshalJ(data []byte, e interface{}) error {

    return json.Unmarshal(data, e)

}


func main() {

    foo := Foo{"Hello", "world!"}

    gob.Register(Foo{})

    data, err := marshal(&foo)

    fmt.Println("got", len(data), err)

    var bar Foo

    err = unmarshal(data, &bar)

    fmt.Println("Main err", err)

    fmt.Println("Main", bar)

    fmt.Println("-------------------------")

    data, err = marshalJ(foo)

    fmt.Println("got J", len(data), err)

    err = unmarshalJ(data, &bar)

    fmt.Println("Main J err", err)

    fmt.Println("Main J", bar)

}

編輯:作為對評論的回應。


預防這樣的問題有時很困難,我認為問題的根源是使用interface{}它會丟棄類型信息,不幸的是,我們對此無能為力(除了為每種類型制作顯式解碼器功能)。第二個“問題”是 gob 只是忽略了類型不匹配而沒有錯誤的事實,因此沒有給我們?nèi)魏侮P于我們做錯了什么的跡象。


我們在解碼端可以做的是添加更嚴格的類型檢查。我們可以要求解碼器將解碼后的值放入 a 中interface{},然后檢查解碼后的類型是否與 的類型匹配e:



type Foo struct {

    A string

    B string

}


func marshal(i interface{}) ([]byte, error) {

    var indexBuffer bytes.Buffer

    encoder := gob.NewEncoder(&indexBuffer)

    err := encoder.Encode(&i)

    return indexBuffer.Bytes(), err

}


func unmarshal(data []byte, e interface{}) (err error) {

    buf := bytes.NewBuffer(data)

    dec := gob.NewDecoder(buf)


    eVal := reflect.ValueOf(e)

    eType := eVal.Type()

    if eVal.Kind() != reflect.Ptr {

        return errors.New("e must be a pointer")

    }


    var u interface{}

    err = dec.Decode(&u)

    uVal := reflect.ValueOf(u)

    uType := uVal.Type()

    if eType.Elem() != uType {

        return fmt.Errorf("decoded type '%s' and underlying type of e '%s' not the same", uType.String(), eType.Elem())

    }


    eVal.Elem().Set(uVal)


    return err

}


func main() {

    foo := Foo{"Hello", "world!"}

    gob.Register(Foo{})

    data, err := marshal(foo)

    fmt.Println("got", len(data), err)

    var bar Foo

    var invalid interface{} = bar

    err = unmarshal(data, &invalid)

    fmt.Println("Main err", err)

    fmt.Println("Main", bar)

    err = unmarshal(data, &bar)

    fmt.Println("Main err", err)

    fmt.Println("Main", bar)

}

輸出:


got 61 <nil>

Main err decoded type 'main.Foo' and underlying type of e 'interface {}' not the same

Main { }

Main err <nil>

Main {Hello world!}


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

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網(wǎng)微信公眾號