首先,先引用一下很多文章中讲到的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, 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)
}
该程序的运行结果为: