如何使用反射提取接口类型名称和包



我需要知道类型名称及其使用反射的路径。类型Type有一个Name()和PkgPath()方法,但是如果类型是接口,它们都返回空。

但是,如果我反映一个函数并提取其参数的类型信息,我就得到了正确的类型信息。我是否应该假设这是前一种情况下的bug ?TypeOf不应该返回相同的类型信息而不管上下文(例如:类型函数参数或值类型)?

我知道类型断言,但我并不总是有一个值来做断言,所以我需要与反射工作。类型信息。

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

下面是一些工作代码: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的实际解决方案之前,这是我的答案。我将把它放在这里,因为我认为它仍然有一些有趣的部分。


首先:对于c, r.k pkgpath()和r.k name()是空的,因为底层类型是指针(*context.valueCtx)。

要解决这个问题,可以使用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使用接口类型。但是对于任何具体的变量,它将使用值的实际类型

在golang中有两种接口,即 faceiface。界面是一个空接口,可以简单地表示为interface {}。接口是一种至少有一个方法的接口,比如:

type MyInterface interface {
    Greeting() string
}

在golang实现中,face和iface都是两个字长的结构体。界面保存数据和数据类型,界面保存数据、接口类型和数据类型。当一个接口被分配给另一个接口时,接口类型信息将被忽略。只有传递给界面的数据和数据类型。

因此,reflect.TypeOf(i interface{})的参数是and eface,没有接口类型信息(即上下文)。上下文(在您的情况下)。所以你不能得到原来的interfacetype

相关内容

  • 没有找到相关文章

最新更新