Golang 反射学习
首先,先引用一下很多文章中讲到的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) %sn",t,t.Method(i).Name) fmt.Println(methType) fmt.Printf("fun (%s) %s%sn",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) } 该程序的运行结果为:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |