我需要知道类型名称及其使用反射的路径。类型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/td1YaHHej9package 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中有两种接口,即 face和iface。界面是一个空接口,可以简单地表示为interface {}
。接口是一种至少有一个方法的接口,比如:
type MyInterface interface {
Greeting() string
}
在golang实现中,face和iface都是两个字长的结构体。界面保存数据和数据类型,界面保存数据、接口类型和数据类型。当一个接口被分配给另一个接口时,接口类型信息将被忽略。只有传递给界面的数据和数据类型。
因此,reflect.TypeOf(i interface{})
的参数是and eface,没有接口类型信息(即上下文)。上下文(在您的情况下)。所以你不能得到原来的interfacetype