反射的基本介绍
反射就是程序在运行时,通过检查其定义的变量以及值,进而找到其对应的真实类型
reflect包
reflect包实现了运行时反射,允许程序操作任意类型的对象。典型用法是用静态类型interface{}保存一个值,通过调用TypeOf获取其动态类型信息,该函数返回一个Type类型值。调用ValueOf函数返回一个Value类型值,该值代表运行时的数据。
reflect.Type和reflect.Value
interface{}类型变量其具体类型可以使用reflect.Tpye来表示,而其具体值则使用reflect.Value来表示
1 | func ValueOf(i interface{}) Value |
ValueOf返回一个初始化为i接口保管的具体值的Value
1 | func TypeOf(i interface{}) Type |
TypeOf返回接口中保存的值的类型
reflect.Kind
reflect还有一个比较重要的类型Kind,表示具体类型
1 | func (v Value) Kind() Kind |
Kind返回v持有的值的分类,如果v是Value零值,返回值为Invalid
- Type代表实际类型,如
包名.Student - Kind代表具体类型,如
struct - 如果使基本数据类型,Type和Kind相同
NumField()和Field()
1 | func (v Value) NumField() int |
返回v持有的结构体类型值的字段数,如果v的Kind不是Struct会panic
1 | func (v Value) Field(i int) Value |
返回结构体的第i个字段(的Value封装)。如果v的Kind不是Struct或i出界会panic
Elem()
1 | func (v Value) Elem() Value |
Elem返回v持有的接口保管的值的Value封装,或者v持有的指针指向的值的Value封装。如果v的Kind不是Interface或Ptr会panic
1 | func reflectElemTest(i interface{}) { |
Method()和Call()
1 | func (v Value) Method(i int) Value |
返回v持有值类型的第i个方法的已绑定(到v的持有值的)状态的函数形式的Value封装。如果i出界,或者v的持有值是接口类型的零值(nil),会panic。
- 方法排序是按照方法名字进行排序
1 | func (v Value) Call(in []Value) []Value |
Call方法使用输入的参数in调用v持有的函数。例如,如果len(in) == 3,v.Call(in)代表调用v(in[0], in[1], in[2])(其中Value值表示其持有值)。如果v的Kind不是Func会panic。它返回函数所有输出结果的Value封装的切片。如果v持有值是可变参数函数,Call方法会自行创建一个代表可变参数的切片,将对应可变参数的值都拷贝到里面。