首先,先引用一下很多文章中讲到的golang类型系统。
类型和接口
由于反射是基于类型系统(type system)的,所以先简单了解一下类型系统。
首先Golang是一种静态类型的语言,在编译时每一个变量都有一个类型对应,例如:int,floate32,[]byte,*MyType等等。如果我们这样声明:
type MyInt int var i int var j MyInt
上面的i是int类型的,j是MyInt类型的。i和j是不同的静态类型,尽管他们都有相同的相关类型(这里就是int),他们不能互相赋值除非通过强制转换。
一种非常重要的类型分类是接口类型,接口代表中方法的集合。只要一个值实现了接口定义的方法,那么这个值就可以存储这个具体的值。一个著名的例子就是io包中的Reader和Writer。
// Reader is the interface that wraps the basic Read method type Reader interface { Read(p []byte) (n int,err error) } // Writer is the interface that wraps the basic Write method type Writer interface { Write(p []byte) (n int,err error) }
任何是实现了Read(或Write)方法的签名的类型就是实现了io.Reader(或者io.Writer)。也就是说一个io.Reader的变量可以持有任何实现了Read方法的值。
var r io.Reader r = os.Stdin r = bufio.NewReader(r) r = new(bytes.Buffer) // and so on
我们要非常清楚的知道不管r持有了哪种具体的值,r的类型永远都是io.Reader。
一个非常重要的的例子就是一个空的接口:
interface{}
这个代表一个空的方法集合并且满足任何值,只要这个值有零个或者多个方法。
有人中golang中的interface是动态类型的,这个一个误导。一个interface类型的变量拥有相同的静态类型,尽管运行时这个变量的值会发生改变,但是都是满足一直都是满足这个interface的。
##interface的表示
Russ Cox曾经写个一篇博文详细讨论了golang中的interface的值。 简单类说,一个interface的值存储了一个赋给变量的具体值和这个值类型的描述。
var r io.Reader tty,err := os.OpenFile("/dev/tty",os.O_RDWR,0) if err != nil { return nil,err } r = tty
这个具体的例子中,r包含了一个(value,type)对,具体的就是(tty,*os.File)。*os.File实现了Read等很多方法,但是io.Reader的接口之允许访问Read方法,所以我们还可以这样做:
var w io.Writer w = r.(io.Writer)
通过类型断言(type assertion),因为r照样实现了io.Writer,所以我们可以将r赋值给w.
reflect.Type和reflect.Value
反射是由 reflect 包提供支持. 它定义了两个重要的类型,Type 和 Value.一个Type表示一个Go类型. 它是一个接口,提供了许多函数来区分类型和检查它们的组件。关于reflect.Type的详细描述可以查看源代码.
在程序中通过reflect.TypeOf函数返回reflect.Type. reflect.TypeOf具有识别接口实际类型的能力.
reflect.ValueOf 函数返回reflect.Value.
// reflect_test project main.go package main import ( "fmt" "reflect" "strconv" "strings" ) type RouterA struct { f1 int f2 string f3 []int } func (this *RouterA) Func_1(name string,a *RouterA) { fmt.Println("exec Func_1!!!!" + name + strconv.Itoa(a.f1)) } func (this *RouterA) Func_2() { fmt.Println("exec Func_2!!!!") } func main() { router := &RouterA{f1: 1009} v := reflect.ValueOf(router) t := v.Type() fmt.Println(v) fmt.Println(t) fmt.Println(reflect.TypeOf(router)) fmt.Println(v.NumMethod()) for i := 0; i < v.NumMethod(); i += 1 { methType := v.Method(i).Type() //fmt.Printf("fun (%s) %s\n",t,t.Method(i).Name) fmt.Println(methType) fmt.Printf("fun (%s) %s%s\n",t.Method(i).Name,strings.TrimPrefix(methType.String(),"func")) } v.Method(0).Call([]reflect.Value{reflect.ValueOf("huangxin"),reflect.ValueOf(router)}) v.Method(1).Call(nil) }
该程序的运行结果为:
原文链接:https://www.f2er.com/go/189102.html