简介
Go反射提供了一种可以在运行时(runtime)操作任意类型对象的能力。
在Go的反射定义中,任何接口都会由两部分组成的,一个是接口的具体类型(Type),一个是具体类型对应的值(Value)。
更精确的描述是,value指的是实现接口的底层具体数据,type指的是数据的完整类型
|
|
Type
Type是对go类型的描述,其方法分为两类,一类是所有类型通用的方法,一类是类型特有方法
通用方法
|
|
kind表示类型种类,比如Bool、Int、Int8等,对应值0-26的常量
const (
Invalid Kind = iota
Bool
Int
Int8
Int16
Int32
Int64
Uint
Uint8
Uint16
Uint32
Uint64
Uintptr
Float32
Float64
Complex64
Complex128
Array
Chan
Func
Interface
Map
Ptr
Slice
String
Struct
UnsafePointer
)
类型特有方法(kind-specific methods)
|
|
Value
Value是一个Go值的反射接口
|
|
Value类型的方法也分为通用方法和类型特定方法两种
|
|
应用
Go反射中把任意一个对象分为reflect.Value和reflect.Type,值得注意的一点是reflect.Value同时持有一个对象的reflect.Value和reflect.Type
reflect.Value与具体类型的转换
|
|
通过reflect.Value获取reflect.type
|
|
获取类型种类
|
|
遍历字段和方法
通过反射,我们可以获取一个结构体类型字段,也可以获取一个类型的导出方法,这样我们可以在运行时了解一个类型的结构
修改字段的值
动态修改某个字段的值有两种办法,一种是直接通过导出的字段或方法修改,另一种是使用反射
reflect.ValueOf函数返回的是一份值的拷贝,所以我们需要传入变量地址来修改原始变量。另外需要调用Elem方法找到这个指针指向的值,最后使用SetInt方法修改值
动态调用方法
结构体方法还可以使用反射进行调用
MethodByName方法可以让我们根据一个方法名获取一个方法对象,然后我们构建好参数,最后通过Call达到动态调用方法的目的(Call方法参数是一个reflect.Value类型的切片)
获取到的方法我们可以使用IsValid来判断是否可用
获取字段Tag
Tag是标记到字段上的,我们要先获取字段,再通过字段获取Tag