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

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)
有關使用反射設置結構字段的值,請參閱以下內容:
- 2 回答
- 0 關注
- 100 瀏覽
添加回答
舉報