zoukankan      html  css  js  c++  java
  • 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. 使用反射创建并操作结构体
  • 相关阅读:
    函数基础
    全局变量与类似配置文件的模块文件
    global语句(python学习手册422页)
    作用域实例
    变量名解析:LEGB原则
    作用域
    第三方库安装方法
    s[-1]和s[len(s)-1]
    查找特定后缀的文件
    logging日志管理-将日志写入文件
  • 原文地址:https://www.cnblogs.com/lxlhelloworld/p/14286064.html
Copyright © 2011-2022 走看看