反射是通过实体对象获取反射对象(Value、Type),然后可以操作相应的方法。在某些情况下,我们可能并不知道变量的具体类型,这时候就可以用反射来获取这个变量的类型或者方法。 一
反射是通过实体对象获取反射对象(Value、Type),然后可以操作相应的方法。在某些情况下,我们可能并不知道变量的具体类型,这时候就可以用反射来获取这个变量的类型或者方法。 一、反射的规则其实反射的操作步骤非常的简单,就是通过实体对象获取反射对象(Value、Type),然后操作相应的方法即可。 下图描述了实例、Value、Type 三者之间的转换关系: 反射 API 的分类总结如下: 1、从实例到 Value通过实例获取 Value 对象,直接使用 reflect.ValueOf() 函数。例如:
2、从实例到 Type通过实例获取反射对象的 Type,直接使用 reflect.TypeOf() 函数。例如:
3、从 Type 到 ValueType 里面只有类型信息,所以直接从一个 Type 接口变量里面是无法获得实例的 Value 的,但可以通过该 Type 构建一个新实例的 Value。reflect 包提供了两种方法,示例如下:
如果知道一个类型值的底层存放地址,则还有一个函数是可以依据 type 和该地址值恢复出 Value 的。例如:
4、从 Value 到 Type从反射对象 Value 到 Type 可以直接调用 Value 的方法,因为 Value 内部存放着到 Type 类型的指针。例如:
5、从 Value 到实例Value 本身就包含类型和值信息,reflect 提供了丰富的方法来实现从 Value 到实例的转换。例如:
6、从 Value 的指针到值从一个指针类型的 Value 获得值类型 Value 有两种方法,示例如下。
7、Type 指针和值的相互转换指针类型 Type 到值类型 Type。例如:
值类型 Type 到指针类型 Type。例如:
8、Value 值的可修改性Value 值的修改涉及如下两个方法:
Value 值在什么情况下可以修改?我们知道实例对象传递给接口的是一个完全的值拷贝,如果调用反射的方法 reflect.ValueOf() 传进去的是一个值类型变量, 则获得的 Value 实际上是原对象的一个副本,这个 Value 是无论如何也不能被修改的。 9、根据 Go 官方关于反射的文档,反射有三大定律:9
第一条是最基本的:反射可以从接口值得到反射对象。 反射是一种检测存储在 interface中的类型和值机制。这可以通过 TypeOf函数和 ValueOf函数得到。 第二条实际上和第一条是相反的机制,反射可以从反射对象获得接口值。 它将 ValueOf的返回值通过 Interface()函数反向转变成 interface变量。 前两条就是说 接口型变量和 反射类型对象可以相互转化,反射类型对象实际上就是指的前面说的 reflect.Type和 reflect.Value。 第三条不太好懂:如果需要操作一个反射变量,则其值必须可以修改。 反射变量可设置的本质是它存储了原变量本身,这样对反射变量的操作,就会反映到原变量本身;反之,如果反射变量不能代表原变量,那么操作了反射变量,不会对原变量产生任何影响,这会给使用者带来疑惑。所以第二种情况在语言层面是不被允许的。 二、反射的使用从relfect.Value中获取接口interface的信息 当执行reflect.ValueOf(interface)之后,就得到了一个类型为”relfect.Value”变量,可以通过它本身的Interface()方法获得接口变量的真实内容,然后可以通过类型判断进行转换,转换为原有真实类型。不过,我们可能是已知原有类型,也有可能是未知原有类型,因此,下面分两种情况进行说明。 1、已知原有类型已知类型后转换为其对应的类型的做法如下,直接通过Interface方法然后强制转换,如下:
示例代码:
运行结果:
说明
2、未知原有类型很多情况下,我们可能并不知道其具体类型,那么这个时候,该如何做呢?需要我们进行遍历探测其Filed来得知,示例如下:
运行结果:
总结获取未知类型的interface的具体变量及其类型的步骤为:
获取未知类型的interface的所属方法(函数)的步骤为:
|
2022-04-28
2022-04-21
2022-05-13
2022-08-17
2022-02-25