Dawn's Blogs

分享技术 记录成长

0%

GO学习笔记 (7) 反射

反射的基本介绍

反射就是程序在运行时,通过检查其定义的变量以及值,进而找到其对应的真实类型

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持有的值的分类,如果vValue零值,返回值为Invalid

  • Type代表实际类型,如包名.Student
  • Kind代表具体类型,如struct
  • 如果使基本数据类型,Type和Kind相同

NumField()和Field()

1
func (v Value) NumField() int

返回v持有的结构体类型值的字段数,如果vKind不是Structpanic

1
func (v Value) Field(i int) Value

返回结构体的第i个字段(的Value封装)。如果vKind不是Structi出界会panic

Elem()

1
func (v Value) Elem() Value

Elem返回v持有的接口保管的值的Value封装,或者v持有的指针指向的值的Value封装。如果vKind不是InterfacePtrpanic

1
2
3
4
5
6
7
8
9
10
11
12
func reflectElemTest(i interface{}) {
// 获取Value
rVal := reflect.ValueOf(i)
// 改变num的值
rVal.Elem().SetInt(20)
}

func main() {
num := 10
reflectElemTest(&num)
fmt.Println(num) // 20
}

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) == 3v.Call(in)代表调用v(in[0], in[1], in[2])(其中Value值表示其持有值)。如果vKind不是Funcpanic。它返回函数所有输出结果的Value封装的切片。如果v持有值是可变参数函数,Call方法会自行创建一个代表可变参数的切片,将对应可变参数的值都拷贝到里面。