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

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

json.Unmarshal 接口指針以及稍后的類型斷言

json.Unmarshal 接口指針以及稍后的類型斷言

Go
揚帆大魚 2023-06-26 16:48:31
因為我經常 unmarshal?http.Response.Body,所以我想我可以編寫一個函數來處理讀取、關閉和解組到各種不同結構中的所有麻煩。這就是為什么我引入了一個函數func unmarhalInterface(closer *io.ReadCloser, v *interface{}) error,然后可以使用 斷言返回值t:=i.(T)。我已經將它包裝成類型的值*interface{},但是因為覆蓋類型是interface{}而不是myStruct,json所以包實現選擇了map[string]interface{}。之后類型斷言就會失敗(當然)。我是否缺少任何內容或需要此實現“手動”進行類型斷言,這意味著查找映射中的所有字段并將我想要的字段分配到我的結構中。下面的代碼有最少的示例,注釋中帶有注釋。如果我的解釋不夠充分,請離開。package mainimport (? ? "bytes"? ? "encoding/json"? ? "fmt"? ? "io"? ? "io/ioutil"? ? "log")type myStruct struct {? ? A string `json:"a"`? ? B string `json:"b"`}func main() {? ? jsonBlob := []byte(`{"a":"test","b":"test2"}`)? ? var foo = interface{}(myStruct{})? ? closer := ioutil.NopCloser(bytes.NewReader(jsonBlob))? ? err := unmarshalCloser(&closer, &foo)? ? if err != nil {? ? ? ? log.Fatal(err)? ? }? ? fmt.Println(fmt.Sprintf("%v", foo))? ? // That´s what i want:? ? foo2 := foo.(myStruct)? ? fmt.Println(foo2.A)}func unmarshalCloser(closer *io.ReadCloser, v *interface{}) error {? ? defer func() { _ = (*closer).Close() }()? ? data, err := ioutil.ReadAll(*closer)? ? if err != nil {? ? ? ? return err? ? }? ? err = json.Unmarshal(data, v)? ? if err != nil {? ? ? ? return err? ? }? ? return nil}
查看完整描述

1 回答

?
蠱毒傳說

TA貢獻1895條經驗 獲得超3個贊

空接口不是實際類型,它基本上是匹配任何內容的東西。正如評論中所述,指向空接口的指針實際上沒有意義,因為指針已經與空接口匹配,因為所有內容都與空接口匹配。為了讓你的代碼正常工作,你應該刪除結構周圍的接口包裝器,因為這只會擾亂 json 類型檢查,而空接口的全部意義在于你可以向它傳遞任何內容。


package main


import (

    "bytes"

    "encoding/json"

    "fmt"

    "io"

    "io/ioutil"

    "log"

)


type myStruct struct {

    A string `json:"a"`

    B string `json:"b"`

}


func main() {

    jsonBlob := []byte(`{"a":"test","b":"test2"}`)


    var foo = &myStruct{} // This need to be a pointer so its attributes can be assigned

    closer := ioutil.NopCloser(bytes.NewReader(jsonBlob))


    err := unmarshalCloser(closer, foo)

    if err != nil {

        log.Fatal(err)

    }

    fmt.Println(fmt.Sprintf("%v", foo))


    // That′s what i want:

    fmt.Println(foo.A)

}


// You don't need to declare either of these arguments as pointers since they're both interfaces

func unmarshalCloser(closer io.ReadCloser, v interface{}) error {

    defer closer.Close()

    // v NEEDS to be a pointer or the json stuff will barf


    // Simplified with the decoder

    return json.NewDecoder(closer).Decode(v)

}


查看完整回答
反對 回復 2023-06-26
  • 1 回答
  • 0 關注
  • 169 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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