2015-10-18 92 views
2

我需要知道使用反射的類型名稱及其路徑。類型Type具有Name()和PkgPath()方法,但如果類型是接口,則它們都會返回空值。如何使用反射提取接口類型名稱和包?

但是,如果我反映一個函數並提取其參數的類型信息,我會得到正確的類型信息。我應該認爲這是前一種情況下的錯誤嗎?不管TypeOf是否返回相同的類型信息(例如,類型函數參數或值的類型)?

我知道類型斷言,但我並不總是有價值做斷言,所以我需要使用reflect.Type信息。

package main 

import (
    "fmt" 
    "reflect" 
    "golang.org/x/net/context" 
) 

func main() { 
    c := reflect.TypeOf(withValue("")) 
    fn := func(context.Context){} 
    fc := reflect.TypeOf(fn).In(0) 
    fmt.Println(isContext(c), isContext(fc), c, fc) 
} 

func isContext(r reflect.Type) bool { 
    return r.PkgPath() == "golang.org/x/net/context" && r.Name() == "Context" 
} 


func withValue(v interface{}) context.Context { 
    return context.WithValue(context.TODO(), "mykey", v) 
} 

打印

false true *context.valueCtx context.Context 
+0

對於我的同伴回答者,可運行的操場鏈接:https://play.golang.org/p/fnjfVl1anv – HectorJ

回答

2

下面是一些工作代碼:https://play.golang.org/p/ET8FlguA_C

package main 

import (
    "fmt" 
    "reflect" 
) 

type MyInterface interface { 
    MyMethod() 
} 

type MyStruct struct{} 

func (ms *MyStruct) MyMethod() {} 

func main() { 
    var structVar MyInterface = &MyStruct{} 
    c := reflect.TypeOf(structVar) 

    fn := func(MyInterface) {} 
    fc := reflect.TypeOf(fn).In(0) 

    fmt.Println(isMyInterface(c), isMyInterface(fc), c, fc) 
    // OP expects : "true true main.MyInterface main.MyInterface" 
} 

func isMyInterface(r reflect.Type) bool { 
    // TypeOf trick found at https://groups.google.com/forum/#!topic/golang-nuts/qgJy_H2GysY 
    return r.Implements(reflect.TypeOf((*MyInterface)(nil)).Elem()) 
} 

這裏是我的回答之前,我找到了一個解決方案的實際用reflect。 我會讓它在這裏,因爲我認爲它仍然有一些有趣的部分。


首先:因爲底層類型是一個指針(*context.valueCtx)爲c,r.PkgPath()和r.Name()是空的。

爲了解決這個問題,你可以使用c := reflect.Indirect(reflect.ValueOf(withValue(""))).Type()

但是,這並不讓isContext(c)真實的,因爲你再有r.PkgPath() == "golang.org/x/net/context" && r.Name() == "valueCtx"

,最好的方法來檢查,如果VAR實現一個接口是下降的反射和使用類型斷言這樣的:

https://play.golang.org/p/td1YaHHej9

package main 

import "fmt" 

type MyInterface interface { 
    MyMethod() 
} 

type MyStruct struct{} 

func (ms *MyStruct) MyMethod() {} 

func main() { 
    var structVar MyInterface = &MyStruct{} 

    fmt.Println(isMyInterface(structVar)) 
} 

func isMyInterface(object interface{}) bool { 
    _, ok := object.(MyInterface) 
    return ok 
} 

,你期望與功能參數你的代碼工作因爲沒有底層價值,所以reflect使用接口類型。但對於任何具體的變量,它將使用值的實際類型。

相關問題