一、基本介绍

1、反射可以在运行时动态获取变量的各种信息,比如变量的类型、类别;

2、如果是结构体变量,还可以获取到结构体本身的信息(包括结构体的字段、方法);

3、通过反射,可以修改变量的值,可以调用关联的方法;

4、使用反射,需要import "reflect".

5、示意图:

示意图
说明

1、反射的应用场景

1、不知道接口调用哪个函数,根据传入参数在运行时确定调用的具体接口,这种需要对函数或方法反射。

例如以下这种桥接模式:

桥接模式

示例第一个参数funcPtr以接口的形式传入函数指针,函数参数args以可变参数的形式传入,bridge函数中可以用反射来动态执行funcPtr函数。

2、反射重要的函数和概念

1、reflect.TypeOf(变量名),获取变量的类型,返回reflect.Type类型。

2、reflect.ValueOf(变量名),获取变量的值,返回reflect.Value类型reflect.Value是一个结构体类型。

3、变量、interface{}和reflect.Value是可以互相转换的,这点在实际开发中,会经常使用到。

示意图
转换说明图


二、反射的注意事项

1、reflect.Value.Kind,获取变量的类别(Kind),返回的是一个常量。在go语言文档中:

Kind

示例如下所示:

示例

输出如下:

输出

Kind的范畴要比Type大。比如有Student和Consumer两个结构体,他们的Type分别是StudentConsumer,但是它们的Kind都是struct


2、Type是类型,Kind是类别,Type和Kind可能是相同的,也可能是不同的。

Type和Kind


3、通过反射可以在让变量interface{}Reflect.Value之间相互转换,这点在前面画过示意图。


4、使用反射的方式来获取变量的值(并返回对应的类型),要求数据类型匹配,比如x是int,那么久应该使用reflect.Value(x).Int(),而不能使用其它的,否则报panic。

示例

如果是x是float类型的话,也是要用reflect.Value(x).Float()。但是如果是struct类型的话,由于type并不确定,所以没有相应的方法,只能断言。

示例


5、通过反射的来修改变量,注意当使用SetXxx方法来设置需要通过对应的指针类型来完成,这样才能改变传入的变量的值,同时需要使用到reflect.Value.Elem()方法。

示例

输出num=20,即成功使用反射来修改传进来变量的值。

输出结果


6、reflect.Value.Elem()应该如何理解?

示意图