Go的反射

反射的基本介绍

  1. 反射可以在运行时动态获取变量的各种信息,比如变量的类型(type),类别(kind)
  2. 如果是结构体变量,还可以获取到结构体本身的信息(包括结构体的字段、方法)
  3. 通过反射,可以修改变量的值,可以调用关联的方法
  4. 使用反射,需要 import "reflect"

反射应用场景

  1. 序列化与反序列化(json的应用场景,结构体指定tag)
  2. 反射机制编写函数的适配器,桥连接

反射重要函数和概念

  1. reflect.TypeOf(变量名),获取变量的类型,返回reflect.Type类型(接口类型,具体看文档)
  2. reflect.ValueOf(变量名),获取变量的值,返回reflect.Value类型(结构体类型,具体看文档)
  3. 变量、interface{} 和 reflect.Value是可以相互转换的,这点在实际开发中,会经常使用到。
    • 变量 --> interface{}:传递参数,或者强转
    • interface{} --> reflect.Value:通过reflect.Value()函数
    • reflect.Value --> interface{}: v.interface{},v的类型为reflect.Value
    • interface{} --> 变量:类型断言
type Student struct {
	Name string
	Age int
}

func ReflectTest01(b interface{}) {

	// 通过反射获取传入的变量的type,kind值
	rType := reflect.TypeOf(b)
	fmt.Println("rTpye = ", rType)

	// 获取到reflect.Value
	rVal := reflect.ValueOf(b)
	fmt.Printf("rVal = %v, rval type = %T
", rVal, rVal)

	n2 := 2 + rVal.Int()
	fmt.Println("n2 = ", n2)

	// rVal 转成 interface{}
	iV := rVal.Interface()

	// iV 转成 变量
	num := iV.(int)
	fmt.Println("num = ", num)
	
}

func ReflectTest02(b interface{}) {

	// 通过反射获取传入的变量的type,kind值
	rType := reflect.TypeOf(b)
	fmt.Println("rTpye = ", rType)

	// 获取到reflect.Value
	rVal := reflect.ValueOf(b)
	fmt.Printf("rVal = %v, rval type = %T
", rVal, rVal)

	// rVal 转成 interface{}
	iV := rVal.Interface()
	fmt.Printf("iv = %v, iv type = %T
", iV, iV)

	// iV 转成 变量
	stu, ok := iV.(Student)
	if ok {
		fmt.Println(stu)
	}
	
}

反射的注意事项和细节

  1. reflect.Value.Kind, 获取变量的类别,返回的是一个常量
  2. Type和Kind的区别
    • Type是类型,Kind是类别,Type和Kind可能是相同的,也可能是不同的
  3. 通过反射可以在让变量在interface{} 和 Reflect.Value之间相互转换:变量 <---> interface{} <---> reflect.Value
  4. 使用反射的方式来获取变量的值(并返回对应的类型),要求数据类型匹配,比如x是int,那么就应该使用reflect.Value(x).Int(), 而不能使用其他的,否则包panic
  5. 通过反射的来修改变量,注意当使用SetXxx方法来设置需要通过对应的指针类型来完成,这样才能改变传入的变量的值,它融合是需要使用到reflect.Value.Elem()方法

写出反射的几个例子

  1. 使用反射来遍历结构体的字段,调用结构体的方法,并获取结构体标签的值
  2. 使用反射的方式来获取结构体的tag标签,遍历字段的值,修改字段值,调用结构体方法
  3. 定义了两个函数test1和test2,定义一个适配器函数用统一处理接口
  4. 使用反射操作任意结构体类型
  5. 使用反射创建并操作结构体
原文地址:https://www.cnblogs.com/lxlhelloworld/p/14286064.html