反射:Go语言提供了一种机制,能够在运行时更新、检查变量值,调用方法,而不需要在编译时就知道这些变量具体类型。这种机制被称为反射。
反射的基本使用:
- 在运行时动态地获取变量的信息。Type类型、Value类型、Kind(类别)。
- 在运行时动态地获取结构体信息:字段、方法。
- 在运行时动态修改变量值,调用结构体方法。
反射使用的基本原理:
- 变量->TypeOf()->Type类型(interface)->interface{Kind()/Field()/NumField()/Method()/Name()}
- 变量->ValueOf()->Value类型(struct)->可以调用{Kind()/Field()/NumField()/Method()/Call()/Elem()}
反射的应用:
基础类型:
- 变量->interface->ValueOf()->v = reflect.Value->v.interface()->类型断言->int
- 变量->interface->ValueOf()->v = reflect.Value->Int()、Bool()、Float()
结构体类型:
获取变量的kind:
- reflect.Type.Kind()->对应变量的具体 kind 类别。可以从reflect包中的常量列表中对比
- reflect.Value.Kind()->对应变量的具体 kind 类别。可以从reflect包中的常量列表中对比
设置变量值:
- a := 100
- pa := &a
- reflect.ValueOf(pa).Elem().SetInt(1000)
- Value类型的方法,而不是*Value类型的方法,想要改变Value的值,需要传入指针,再使用Elem(),最后SetXXX()
获取结构体的值:
- 定义结构体类型,带有tag标签
type Test struct {
Name string `Testing:"-"`
Age int `Testing:"age,omitempty"`
Id int `Testing:"idx,string"`
Sex string `Testing:"sex"`
}
- 初始化结构体变量
test := Test{xxx, xxx, xxx}
- 封装使用反射的函数
reflectGetStruct(i interface)
- 获取reflect.Type类型interface{kind(), Name(), NumField(), Field()…}
- 获取reflect.Value类型 reflect.ValueOf(struct)
- 获取结构体的字段数
- 以reType.NumField做循环上限,for取出每一个字段reType.Field(i),得到StructField{}结构体
- 依次取出Name、Type、Tag
- 取Tag,然后Get()
type Test struct {
Name string `json:"-"` //忽略处理
Age int `json:"age,omitempty"` //序列化时,忽略零值和空值
Id int `json:"idx,string"` //序列化时,转成字符串
Sex string `json:"sex"`
}
反射调用结构体方法:
func (v Value)NumMethod() int
func (v Value)Method(i int) Value
func (v Value)Call(in []Value) []Value