网站建站公司一站式服务,重庆室内设计公司,网站的域名怎么看,行业门户网站案例分析在 go 语言中#xff0c;实现反射能力的是 reflect包#xff0c;能够让程序操作不同类型的对象。其中#xff0c;在反射包中有两个非常重要的 类型和 函数#xff0c;两个函数分别是#xff1a;
reflect.TypeOfreflect.ValueOf 两个类型是 reflect.Type 和 reflect.Value…在 go 语言中实现反射能力的是 reflect包能够让程序操作不同类型的对象。其中在反射包中有两个非常重要的 类型和 函数两个函数分别是
reflect.TypeOfreflect.ValueOf 两个类型是 reflect.Type 和 reflect.Value它们与函数是一一对应的关系
使用场景map和struct的相互转化json序列化ORM框架rpc服务的注册和调用
1 Type 和 TypeOf
reflect.Type 类型是一个接口类型内部指定了若干方法通过这些方法我们可以获取到反射类型的各种信息例如字段、方法等 使用 reflect.TypeOf() 函数可以获取将任意值的类型对象 (reflect.Type)程序通过类型对象可以访问任意值的类型信息
func main() {type MyInt inttype cat struct {Name stringType int json:type id:100}inst : cat{Name: mimi, Type: 1}typeOfCat : reflect.TypeOf(inst)// 显示反射类型对象的名称和种类fmt.Println(typeOfCat.Name(), typeOfCat.Kind())for i : 0; i typeOfCat.NumField(); i {// 获取每个成员的结构体字段类型fieldType : typeOfCat.Field(i)// 输出成员名和tagfmt.Printf(name: %v tag: %v\n, fieldType.Name, fieldType.Tag)}// 通过字段名, 找到字段类型信息if catType, ok : typeOfCat.FieldByName(Type); ok {// 从tag中取出需要的tagfmt.Println(catType.Tag.Get(json), catType.Tag.Get(id))}var Zero MyInt// 获取Zero常量的反射类型对象typeOfA : reflect.TypeOf(Zero)// 显示反射类型对象的名称和种类fmt.Println(typeOfA.Name(), typeOfA.Kind())
}2 Value 和 ValueOf
reflect.Value 类型是一个结构体封装了反射对象的值内部若干方法可以通过这些方法来获取和修改对象的值使用 reflect.ValueOf 函数可以返回 Value 类型value 类型还可以生成原始类型对象
反射值对象reflect.Value提供对结构体访问的方法通过这些方法可以完成对结构体任意值的访问方法列表参考 Type 常用方法 修改成员的值 使用 reflect.Value 对包装的值进行修改时需要遵循一些规则。如果该对象不可寻址或者成员是私有的则无法修改对象值
func main() {type dog struct {LegCount intage int}// 获取dog实例地址的反射值对象valueOfDog : reflect.ValueOf(dog{})// 取出dog实例地址的元素valueOfDog valueOfDog.Elem()// 获取legCount字段的值vLegCount : valueOfDog.FieldByName(LegCount)vAge : valueOfDog.FieldByName(age)// 尝试设置legCount的值vLegCount.SetInt(4)// 这里会报错vAge.SetInt(4)fmt.Println(vLegCount.Int())
}3 通过反射调用函数
使用反射调用函数时需要将参数使用反射值对象的切片 []reflect.Value 构造后传入 Call() 方法中调用完成时函数的返回值通过 []reflect.Value 返回
package main
import (fmtreflect
)
// 普通函数
func add(a, b int) int {return a b
}
func main() {// 将函数包装为反射值对象funcValue : reflect.ValueOf(add)// 构造函数参数, 传入两个整型值paramList : []reflect.Value{reflect.ValueOf(10), reflect.ValueOf(20)}// 反射调用函数retList : funcValue.Call(paramList)// 获取第一个返回值, 取整数值fmt.Println(retList[0].Int())
}4 反射性能
通过反射生成对象和字段赋值都会影响性能但是通过反射的确确确实实能简化代码为业务逻辑提供统一的代码 比如标准库中json的编解码、rpc服务的注册和调用 一些ORM框架比如gorm等都是通过反射处理数据的这是为了能处理通用的类型。