定义一个适配器作为函数的统一处理接口, 实现多个函数用同一个入口进入调用
获取结构体的Tag标签
reflect.Value & reflect.Type 是两个反射的结构体类型
这两个类型分别实现了很多的方法,当某个变量转换成这两个类型,就可使用反射的很多方法
比如
type Type interface{
Kind() Kind
…
}
reflect.ValueOf(变量名)
返回变量对应的reflect.Value类型
reflect.TypeOf(变量名)
返回变量对应的reflect.Type类型
1) Kind是变量的类别,本质上kind是一个常量
比如type Student struct{}
:Student是一个类型, struct就是他的类别。
const (
Invalid Kind = iota
Bool
Int
Int8
Int16
Int32
Int64
Uint
Uint8
Uint16
Uint32
....
2) kind与Type可能是相同or可能是不同的
当变量是基本类型时相同:var num int = 100 : kind = type = int
当变量是结构体or其他时候:var stu Student : kind=struct
(结构体), type=Student
(结构体名)
3)获取类别的方法:
(Value or Type).Kind(变量名) Kind
返回变量的Kind类别func testReflect02(b interface{
}) {
rType := reflect.TypeOf(b)
rVal := reflect.ValueOf(b)
// 3. 获取变量对应的kind
kind1 := rType.Kind()
kind2 := rVal.Kind()
fmt.Printf("kind1=%v, kind2=%v\n", kind1, kind2)//kind1=struct, kind2=struct
NumField():返回对应的结构体有几个字段
(reflect.Value).Field(i int) 返回结构体变量的第i个字段值
type Stu struct{
Name string
Age int
}
student := Stu{
"zhangsan", 99}
val := reflect.ValueOf(student)
val.Field(0) : 返回"张三" student第一个字段Name的值
val.Field(1) : 返回99 student第二个字段Age的值
val.NumField() == 2 :这个结构体一共有2个字段(即使只赋值了1个字段)
Elem()相当于什么?
如果要进行反射的是一个指针变量,那么 reflect.ValueOf(变量名)以及TypeOf都会返回变量指针对应的地址。
那么 ().Kind() 将得到地址对应的类别
().Field(i) 将无法获取到字段值
().SetXxx() 改变值时会panic
因此对于指针变量,需要用Elem()来获取指针对应的值
如何使用Elem()?
在调用Kind()、Field()之前调用Elem()就可以了,调用了Elem()之后使用和非指针变量方式一样
reflect.ValueOf(&变量名).Elem().Kind()
3.Elem()相当于获取指针的值 & *的方式
**func (v Value).SetInt(新的值 int64)**的作用
改变旧的值
使用
.Elem()
来获取变量的值var b int = 100
rVal := reflect.ValueOf(&b) //获取到的是b的地址,并且修改
rVal.Elem().SetInt(20) //相当于获取到地址对应的值
注意事项
在使用SetXxx之前需要先判断传入的等待改变的变量是否为指针
kd := val.Kind()
if kd != reflect.Ptr
原来变量的类型必须与新的变量类型匹配
[toc]
变量、interface{}、reflect.Value三者之间可以相互转换
1.基本数据类型,interface(),reflet.Value之间的相互转换
reflect.TypeOf() 返回的类型的 reflect.Type
虽然print出来看到的值是 比如rVal = 100, 但是这个100不是传统类型,不能用于
rVal + 22 : miss mathch reflect.Type and int 两个不同的类型不能相加
要想相加需要将reflect.Value类型转换成对应的基本类型才可以,比如上面的rVal.Int()
- 或者用类型断言实现Type转换成int类型
// 练习1:对基本数据类型,interface(),refletValue的基本反射操作
// 专门演示反射操作
func testReflect01(b interface{
}) {
// 1. 获取reflect.Type
rType := reflect.TypeOf(b)
fmt.Println("rType=", rType) //rType= int
// 2. 获取reflect.Value 获取变量的reflect值,对应的值是reflect.Value这个类型
rVal := reflect.ValueOf(b)
fmt.Printf("rVal:%v, rVal Type:%T\n", rVal, rVal) //rVal:100, rVal Type:reflect.Value
// 2.1 将reflect.Type转换成对应传统类型才能和传统类型相加,否则类型不匹配
// num := rVal + 100 : cannot convert 100 (untyped int constant) to reflect.Value
//下面是转换成传统类型的办法
// 方法一:通过reflect包类型转换
num1 := 20 + rVal.Int()
// 方法二:通过类型断言 转换: 先将reflect变量转为interface
rValInter := rVal.Interface(