首頁 > 後端開發 > Golang > 如何在interface{}上使用reflect.NewAt?

如何在interface{}上使用reflect.NewAt?

WBOY
發布: 2024-02-09 14:00:24
轉載
956 人瀏覽過

如何在interface{}上使用reflect.NewAt?

php小編新一為您介紹如何在interface{}上使用reflect.NewAt。 reflect.NewAt是Go語言中的反射庫函數,用於在給定的介面類型上建立新的實例。透過使用reflect.NewAt,我們可以動態地建立並初始化一個新的介面實例,而不需要在編譯時指定特定的類型。這為我們提供了更大的靈活性和動態性,使得程式碼可以更加通用和可擴展。以下將為您詳細解答如何使用reflect.NewAt在interface{}上建立實例。

問題內容

package main

import (
    "encoding/json"
    "fmt"
    "reflect"
    "unsafe"
)

type Stu struct {
    Name string `json:"name"`
}

func MakeStu() interface{} {
    return Stu{
        Name: "Test",
    }
}

func main() {
    jsonData := []byte(`{"name":"New"}`)
    t1 := MakeStu()
    t2 := MakeStu()
    t3 := MakeStu()

    json.Unmarshal(jsonData, &t1)
    fmt.Println(t1) //Type of t1 becomes map[string]interface{} instead of struct Stu

    newPointer := reflect.New(reflect.ValueOf(t2).Type()).Interface()
    json.Unmarshal(jsonData, newPointer)
    fmt.Println(newPointer) //It works,but it need allocate memory to hold temp new variable

    brokenPointer := reflect.NewAt(reflect.ValueOf(t3).Type(), unsafe.Pointer(&t3)).Interface()
    json.Unmarshal(jsonData, brokenPointer)
    fmt.Println(brokenPointer) // I want to get the pointer of original type based on the existed variable t3,but it crashes.
}
登入後複製

如果我在編碼時不知道interface{}的具體類型,就無法使用interface.(type)進行強制轉換。 那麼如何在interface{}上使用reflect.newat呢?

如果有一個接口,其中包含一個返回interface{}的方法,其具體類型是struct,但我在編碼時無法確定struct的類型。我需要使用 json.unmarshal 來解碼 json 編碼的資料。我不想獲得 map[string]interface{} ,所以我需要將接收者的類型設為 interface{} 的具體類型的指標。使用reflect.new 很簡單,但會消耗額外的內存,因此我很好奇如何將reflect.newat 與現有介面一起使用{}。

解決方法

我想花幾句話解釋一下問題所在。

我們無法控制的函數 makestu() 傳回空介面 - 不是具體類型。這將使具體類型對json.unmarshal() “不可見”,並且json.unmarshal() 將其視為空接口,而不是具體類型stu。我們必須以某種方式將具體類型傳達給解組器。

我會用型別開關解決這個問題:

func main() {
    jsondata := []byte(`{"name":"new"}`)
    t1 := makestu()

    switch c := t1.(type) {
    default:
        _ = json.unmarshal(jsondata, &c)
        t1 = c
    }

    fmt.println(t1)
}
登入後複製

類型開關將空介面轉換為具體類型,並且 json.unmarshal() 會將其視為具體類型。您可能仍然會有額外的分配,但程式碼更具可讀性,而且您不依賴反射。

如果我真的很喜歡冒險,我會新增一個輔助函數,接受指向空介面的指針,如下所示:

func unmarshal(data []byte, i *interface{}) (err error) {
    switch c := (*i).(type) {
    default:
        err = json.unmarshal(data, &c)
        *i = c
    }

    return err
}
登入後複製

這將啟用這樣的用法:

    jsonData := []byte(`{"name":"New"}`)
    t1 := MakeStu()
    unmarshal(jsonData, &t1)
登入後複製

這對我來說看起來很乾淨,並且不涉及反射,但它沒有像您自己建議的那樣使用 reflect.newat() 。我希望您發現我的建議仍然有用。

以上是如何在interface{}上使用reflect.NewAt?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:stackoverflow.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板