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

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

從界面獲取反射結構

從界面獲取反射結構

Go
MMMHUHU 2022-10-04 16:41:41
有這個函數的獲取類型的值,但我嘗試這個,從來沒有得到反射.struct:type Test struct {    Code int       Name string}func main(){    test := getTest()    data, err := getBytes(slice...)    sanitizedFile := bytes.Split(data, []byte("\r\n"))    err = Unmarshal(sanitizedFile[0], &test)}func getTest() interface{} {    return Test{}}有了這個代碼,我無法從Unmarshall func中的v參數中獲取replecet.structfunc Unmarshal(data []byte, v interface{}) error {    rv := reflect.ValueOf(v)    if rv.Kind() == reflect.Ptr {        rvElem := rv.Elem()                switch rvElem.Kind() {        case reflect.Struct:           // implement me        }    }    return ErrInvalid}我想知道我是否可以以某種方式找出接口是否屬于結構類型或訪問該結構的值。
查看完整描述

2 回答

?
侃侃爾雅

TA貢獻1801條經驗 獲得超16個贊

我認為這里真正的問題可以通過這句話來說明:


我想知道我是否可以以某種方式找出接口是否屬于結構類型或訪問該結構的值。


接口值不是“結構類型”。從不!接口值可以包含類型為某種結構的值,但它不是該類型的值。它只包含一個。這類似于您從亞馬遜獲得的盒子1可以包含開瓶器的方式,但盒子永遠不是開瓶器。


給定某個接口類型的非 nil 值,您知道您有一個實現 的方法的值。由于 是空的方法集,所有類型都實現它,因此給定類型(仍然是非 nil)值,您有一個不實現任何方法的值。這本身根本沒有用:這意味著你不能調用任何方法,這意味著你不能做任何類似方法的事情。interface III{}interface{}


但是,僅僅因為你不能做任何事情,方法-y并不意味著你根本不能做任何事情。任何接口值(無論接口類型如何)都可以在其上使用類型斷言:


iv := somethingThatReturnsAnInterface()

cv := iv.(struct S) // assert that iv contains a `struct S`

如果確實包含一個值(如果打開它后,這就是盒子里的內容),那么這種類型斷言不會驚慌失措,并且最終會得到類型的具體值。如果不需要 panic,我們可以使用表單或類型開關。所有這些(包括崩潰的版本)都通過檢查接口內的值的類型來工作。ivstruct Scvstruct Scv, ok := iv.(struct S)


這個——或者更準確地說,Go語言的定義方式——告訴我們的是,“盒子”實際上包含兩樣東西:interface


具體類型,以及

一個具體的價值。

好吧,也就是說,除非它持有<無,無>對,在這種情況下是真的。請注意,該測試實際上測試了這兩個部分。iv == niliv == nil


如果Go有一個語法,我們可以寫一些類似的東西,以獲得兩個獨立的部分。但我們不能那樣做。我們必須使用類型斷言、類型切換或 。所以,回到這個:iv.typeiv.valuereflect


我想知道我是否可以以某種方式找出接口是否是結構類型


我們可以看到,問題本身只是有點畸形。我們不想知道接口值是否具有此類型。我們想知道非nil接口的持有值是否屬于這種類型,就好像我們可以直接檢查一樣。iv.typeiv.value


如果一組有限的可能類型,則可以使用類型開關構造,并枚舉所有允許的可能性:


switch cv := iv.(type) {

case struct S:

    // work with cv, which is a struct S

case *struct S:

    // work with cv, which is a *struct S

// add more cases as appropriate

}

如果您需要更通用的內容,而不是執行上述操作,我們最終將使用該包:reflect


tv := reflect.TypeOf(iv)

藝術


vv := reflect.ValueOf(iv)

后者實際上是更有用的形式,因為捕獲偽場和偽場。vviv.typeiv.value


正如 mkopriva 在注釋中指出的那樣,在您的示例代碼中,具有 類型 ,類型 也是如此。在大多數情況下,這不是一個好主意:您只想直接傳遞值。testinterface{}&test*interface{}interface{}


若要允許被調用函數將對象設置為新值,您需要將指向該對象的指針作為接口值傳遞。您不希望傳遞指向接口的指針,同時讓接口將結構“放在框中”。您需要一個可以調用的 ,并且要獲取一個,您需要跟隨 一個 on the,它是指向結構的指針(而不是指向接口的指針)。reflect.ValueSet()elemreflect.Value



查看完整回答
反對 回復 2022-10-04
?
一只萌萌小番薯

TA貢獻1795條經驗 獲得超7個贊

也許你需要的是類型斷言?

t, 確定 := v.(我的結構)

https://tour.golang.org/methods/15

在任何情況下,此代碼都會打印“結構”:

 type tt struct {}


    var x tt

    var z interface{}

    z = x

    v := reflect.ValueOf(z).Kind()

    fmt.Printf("%v\n", v)

有關使用反射設置結構字段的值,請參閱以下內容:

使用反射,如何設置結構字段的值?


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

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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