• Go 反射reflect包


    Go语言中的变量是分为两部分的:

    • 类型信息:预先定义好的元信息。   TypeOf
    • 值信息:程序运行过程中可动态变化的。ValueOf
    import (
    	"reflect"
    )

    比较两个引用类型的值是否相等(写单元测试要用),比较值类型用“==”号

    例如:比较两个切片的值 是否相等

    reflect.DeepEqual( ret , want )     //相等返回true

    func DeepEqual(a1, a2 interface{}) bool

    用来判断两个值是否深度一致:除了类型相同;在可以时(主要是基本类型)会使用==;但还会比较array、slice的成员,map的键值对,结构体字段进行深入比对。

    map的键值对,对键只使用==,但值会继续往深层比对。DeepEqual函数可以正确处理循环的类型。函数类型只有都会nil时才相等;空切片不等于nil切片;还会考虑array、slice的长度、map键值对数。

    通过反射设置变量的值

    想要在函数中通过反射修改变量的值,需要注意函数参数传递的是值拷贝,必须传递变量地址才能修改变量值。而反射中使用专有的Elem()方法来获取指针对应的值。

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    func reflectSetValue1(x interface{}) {
    	v := reflect.ValueOf(x)
    	if v.Kind() == reflect.Int64 {
    		v.SetInt(200) //修改的是副本,reflect包会引发panic
    	}
    }
    func reflectSetValue2(x interface{}) {
    	v := reflect.ValueOf(x)
    	// 反射中使用 Elem()方法获取指针对应的值
    	if v.Elem().Kind() == reflect.Int64 {
    		v.Elem().SetInt(200)
    	}
    }
    func main() {
    	var a int64 = 100
    	// reflectSetValue1(a) //panic: reflect: reflect.Value.SetInt using unaddressable value
    	reflectSetValue2(&a)
    	fmt.Println(a)
    }

    IsNil()常被用于判断指针是否为空;IsValid()常被用于判定返回值是否有效。

    func main() {
    	// *int类型空指针
    	var a *int
    	fmt.Println("var a *int IsNil:", reflect.ValueOf(a).IsNil())
    	// nil值
    	fmt.Println("nil IsValid:", reflect.ValueOf(nil).IsValid())
    	// 实例化一个匿名结构体
    	b := struct{}{}
    	// 尝试从结构体中查找"abc"字段
    	fmt.Println("不存在的结构体成员:", reflect.ValueOf(b).FieldByName("abc").IsValid())
    	// 尝试从结构体中查找"abc"方法
    	fmt.Println("不存在的结构体方法:", reflect.ValueOf(b).MethodByName("abc").IsValid())
    	// map
    	c := map[string]int{}
    	// 尝试从map中查找一个不存在的键
    	fmt.Println("map中不存在的键:", reflect.ValueOf(c).MapIndex(reflect.ValueOf("娜扎")).IsValid())
    }

    结构体反射示例

    type student struct {
    	Name  string `json:"name"`
    	Score int    `json:"score"`
    }
    
    func main() {
    	stu1 := student{
    		Name:  "小王子",
    		Score: 90,
    	}
    
    	t := reflect.TypeOf(stu1)
    	fmt.Println(t.Name(), t.Kind()) // student struct
    	// 通过for循环遍历结构体的所有字段信息
    	for i := 0; i < t.NumField(); i++ {
    		field := t.Field(i)
    		fmt.Printf("name:%s index:%d type:%v json tag:%v
    ", field.Name, field.Index, field.Type, field.Tag.Get("json"))
    	}
    
    	// 通过字段名获取指定结构体字段信息
    	if scoreField, ok := t.FieldByName("Score"); ok {
    		fmt.Printf("name:%s index:%d type:%v json tag:%v
    ", scoreField.Name, scoreField.Index, scoreField.Type, scoreField.Tag.Get("json"))
    	}
    }
  • 相关阅读:
    openstack 杂记 备忘
    centos7 开机/etc/rc.local 不执行的问题
    Rabbit-service Message queue MQ 验证 校验
    MySQL max_connections 总是 214 。不能设大了? max_connections = 214
    Mariadb-lib
    SQL service 自动解决依赖包 验证
    SQL service
    createrepo
    mkisofs
    【Linux探索之旅】第四部分第三课:文件传输,潇洒同步
  • 原文地址:https://www.cnblogs.com/staff/p/13233106.html
Copyright © 2020-2023  润新知