反射
- 包
reflect
- 反射可以在运行时动态获取变量/实例的各种信息,例如:变量的类型;
- 如果是结构体变量,反射还可以获取到结构体本身的信息(结构体的字段、方法等);
- 通过反射可以修改变量的值,可以调用关联的方法;
反射的相关函数
-
relect.TypeOf(变量名)
: 获取变量的类型,返回 reflect.Type
类型;
-
relect.ValueOf(变量名)
: 获取变量的值,返回 reflect.Value
类型; reflect.Value
是一个结构体类型,通过 reflect.Value
可以获取到关于该变量的很多信息;
-
reflect.Value
需要调用具体类型的方法, 获取转换类型后的值,例如:val.Int()
;具体类型使用断言判断;
-
func (v Value) Interface() (i interface{})
: 此函数将 reflect.Value
转换成空接口;借助断言判断并转换成真实类型;
-
type Type
func TypeOf(i interface{
}) Type
func PtrTo(t Type) Type
func SliceOf(t Type) Type
func MapOf(key, elem Type) Type
func ChanOf(dir ChanDir, t Type) Type
type Value
func ValueOf(i interface{
}) Value
...
基本数据类型的反射
- 借助空接口 进行转换;
- 使用
reflect.Value.Int()
转换成真实类型;
- 使用
reflect.Value.Interface()
+ 断言,判断类型并转换成真实类型,进行后续操作;
反射设置变量值
- 需要传入地址;
- 使用
Elem()
:reVal.Elem().SetInt(19)
;
结构体类型的反射
反射操作结构体的属性和方法
-
field := val.NumField();/val.Field(i)
, 输出:NumField 字段个数;Field类似于java 的字段数组;
- 字段修改,传参时需要传入指针;此时操作Field 需要加
reflect.ValueOf().Elem().Field(0)
, Elem 相当于解地址;
- 字段修改使用:
val.Elem().Field(0).SetString("xxx")/ SetInt(18)
, 字段也按结构体的定义先后排序;
- 方法调用:
val.Method(2).Call(nil)
; val.MethodByName("Print").Call(nil)
; 方法首字母必须大写才有对应的反射的访问权限;
- 方法顺序 按照 ASCII 码的顺序排列,使用
val.Method(2).Call(nil)
时传入的2/索引值,需要用到;
- 调用带参数方法,入参要使用
[]reflect.Value
+ append
构造切片;具体看示例代码;
反射获取变量的类别
reflect.Type.Kind()
-
reflect.Value.Kind()
:
- Kind:
type Kind uint
Kind代表Type类型值表示的具体分类。零值表示非法分类。
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
)
示例代码
package main
import (
"fmt"
"reflect"
)
// 函数参数定义为空接口,可接收任何类型的数据
func baseTypeReflect(i interface{
}) {
reType := reflect.TypeOf(i)
fmt.Println("type(reflect.Type 类型)=", reType)
val := reflect.ValueOf(i)
fmt.Println("value(reflect.Value 类型)=", val)
num2 := 10 + val.Int()
fmt.Println("num2=", num2)
fmt.Println("==>> reflect.Value 转换成空接口,再借助断言转换+判断:")
valIface := val.Interface()
valInt, ok := valIface.(int)
if ok {
n2 := valInt +1
fmt.Println("(valInt )=", valInt)
fmt