45-Golang中的反射
创始人
2024-06-02 06:39:22
0

Golang中的反射

    • 基本介绍
    • 反射的应用场景
    • 反射重要的函数和概念
    • 快速入门
      • 案例一
      • 案例二
    • 反射注意事项和细节说明
    • 反射的最佳实践

基本介绍

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

在这里插入图片描述

反射的应用场景

1.不知道接口调用哪个函数,根据传入参数在运行时确定调用的具体接口,这种需要对函数或方法反射

func bridge(funcPtr interface{}, args ...interface{})

例如以上这种桥接模式,第一个参数funcPtr以接口的形式传入函数指针,函数参数args以可变参数的形式传入,bridge函数中可以用反射来动态执行funcPtr函数

2.对结构体序列化时,如果结构体有指定Tag,也会使用到反射生成对应的字符串。

反射重要的函数和概念

1.reflect.TypeOf(变量名),获取变量的类型,返回reflect.Type类型

2.reflect.ValueOf(变量名),获取变量的值,返回reflect.Value类型reflect.Value是一个结构体类型。通过reflect.Value,可以获取到关于该变量的很多信息。

3.变量,intface{}和reflect.Value是可以相互转换的,这点在实际开发中,会经常使用到

在这里插入图片描述

在这里插入图片描述

快速入门

案例一

编写一个案例,演示对(基本数据类型,interface{},reflect.Value)进行反射的基本操作

package mainimport ("fmt""reflect"
)//专门演示反射
func reflectTest01(b interface{}) {//通过反射获取的传入的变量type,kind,值//1.现获取到reflect.TyperType := reflect.TypeOf(b)fmt.Println("rType=", rType)//2.获取到reflect.ValuerVal := reflect.ValueOf(b)n2 := 2 + rVal.Int() //此处的Int()表示拿到真正的valuefmt.Println("n2=", n2)fmt.Printf("rVal=5=%v rVal type=%T\n", rVal, rVal)//3、将rVal转换成interface{}iV := rVal.Interface()//将interface{}通过断言转化成需要的类型num2 := iV.(int)fmt.Println("num2=", num2)
}func main() {//编写一个案例//编写一个案例,演示对(基本数据类型,interface{},reflect.Value)进行反射的基本操作//先定义一个intvar num int = 100reflectTest01(num)
}
/*
rType= int
n2= 102                           
rVal=5=100 rVal type=reflect.Value
num2= 100   
*/

案例二

编写一个案例,演示对(结构体类型,interface{},reflect.Value)进行反射的节本操作

package mainimport ("fmt""reflect"
)//演示对结构体的反射
func reflectTest(b interface{}) {rTyp := reflect.TypeOf(b)fmt.Println("rType=", rTyp)rVal := reflect.ValueOf(b)iV := rVal.Interface()fmt.Printf("iv=%v iV type=%T", iV, iV)
}type Student struct {Name stringAge  int
}func main() {//定义一个student实例stu := Student{Name: "kunkun",Age:  25,}reflectTest(stu)
}
//rType= main.Student
//iv={kunkun 25} iV type=main.Student

反射注意事项和细节说明

1.reflect.Value.Kind,获取变量的类别,返回的是一个常量

2.Type是类型,Kind是类别,Type和Kind可能是相同的,也可能是不同的

比如:var num int = 10 num 的Type是int,Kind也是int

比如:var stu Student stu的Type是包名.Student,Kind是struct

3.使用反射的方式来获取变量的值(并返回对应的类型),要求数据类型匹配,比如x是int,那么就应该使用reflect.Value(x).int(),而不能使用其他的,否则报panic

5.通过反射的来修改变量,注意当使用SetXxx方法来设置需要通过对应的指针类型来完成,这样才能改变传入的变量的值,同样需要使用到reflect.Value.Elem()方法

package mainimport ("fmt""reflect"
)//通过反射,修改num int的值
//修改student的值func reflect01(b interface{}) {//获取到reflect.ValuerVal := reflect.ValueOf(b)rVal.Elem().SetInt(20)}func main() {var num int = 10reflect01(&num)fmt.Println("num=", num)
}
//rVal.Elem()用于获取指针指向变量,类似
//var num = 10
//var b *int =&num
//*b = 3//num = 20

反射的最佳实践

1.使用反射来遍历结构体的字段,调用结构体的方法,并获取结构体标签的值

package mainimport ("fmt""reflect"
)//定义了一个Monster结构体
type Monster struct {Name  string `json:"name"`Age   int    `json:"age"`Score float32Sex   string
}//方法,显示s的值
func (s Monster) print() {fmt.Println("---start---")fmt.Println(s)fmt.Println("---end---")
}//方法,返回两个数的和
func (s Monster) GetSum(n1, n2 int) int {return n1 + n2
}//方法,接受四个值,给s赋值
func (s Monster) Set(name string, age int, score float32, sex string) {s.Name = names.Age = ages.Score = scores.Sex = sex
}func TestStruct(a interface{}) {//获取reflect.Type类型typ := reflect.TypeOf(a)//获取reflect.Value类型val := reflect.ValueOf(a)//获取到a对应的类型kd := val.Kind()//如果传入的不是struct,就退出if kd != reflect.Struct {fmt.Println("expect struct")return}//获取到该结构体有几个字段num := val.NumField()fmt.Printf("struct has %d fields\n", num)for i := 0; i < num; i++ {fmt.Printf("Field %d: 值为=%v\n", i, val.Field(i))//获取到struct标签,注意需要通过reflect.Type来获取tag标签的值tagVal := typ.Field(i).Tag.Get("json")if tagVal != "" {fmt.Printf("Field %d: tag为=%v\n", i, tagVal)}}numOfMethod := val.NumMethod()fmt.Printf("struct had %d methods\n", numOfMethod)//var params []reflect.Value//方法的排序默认是按照函数名的排序 (ASSCII码)val.Method(1).Call(nil)//调用结构体的第一个方法var params []reflect.Valueparams = append(params, reflect.ValueOf(10))params = append(params, reflect.ValueOf(40))res := val.Method(0).Call(params) //传入的参数是[]reflect.Valuefmt.Println("res=", res[0].Int()) //返回结果,返回的结果是[]reflect.Value
}
func main() {//创建了一个Monster实例var a Monster = Monster{Name:  "kunkun",Age:   25,Score: 30.8,}//将Monster实例传递给TestStruct函数TestStruct(a)
}

相关内容

热门资讯

论坛一周年庆典晚会主持词 论坛一周年庆典晚会主持词  主持词是由主持人于节目进行过程中串联节目的串联词。如今的各种演出活动和集...
最新研讨会主持词 最新研讨会主持词(通用11篇)  主持词分为会议主持词、晚会主持词、活动主持词、婚庆主持词等。在现在...
重阳节的主持词 重阳节的主持词  主持词分为会议主持词、晚会主持词、活动主持词、婚庆主持词等。在人们越来越多的参与各...
记者节活动主持词 记者节活动主持词(精选7篇)  主持词没有固定的格式,他的最大特点就是富有个性。在现今人们越来越重视...
高校运动会开幕式精彩致辞 高校运动会开幕式精彩致辞  在平平淡淡的学习、工作、生活中,大家肯定对各类致辞都很熟悉吧,致辞具有思...
幼儿园六一文艺演出主持词 幼儿园六一文艺演出主持词  20xx年六一文艺演出主持词  尊敬的各位领导、各位老师、亲爱的同学们:...
团拜会主持词 -主持词 团拜会主持词 -主持词大家下午好!腊梅催春至,瑞雪兆丰年!此时窗外虽然大雪纷飞、寒意袭人,但这里却热...
最新三八妇女节活动的主持词 最新三八妇女节活动的主持词(精选10篇)  主持词的写作需要将主题贯穿于所有节目之中。在现在的社会生...
小学师德报告会的主持词 小学师德报告会的主持词各位领导,各位老师:  大家下午好!采撷着金秋十月的累累硕果,收藏着金秋十月的...
《像小强一样儿活着》的经典台... 《像小强一样儿活着》的经典台词  《像小强一样活着》改编自同名网络小说,是难得的本土电影。曾有影评家...
汇演主持词 汇演主持词  主持词要根据活动对象的不同去设置不同的主持词。在人们积极参与各种活动的今天,主持人在各...
联欢会主持词结束语 联欢会主持词结束语(通用6篇)  晚会开得就是否成功圆满与主持人的讲话有很大关系。下面小编整理的联欢...
幼儿园毕业晚会主持词 幼儿园毕业晚会主持词  主持人在台上表演的灵魂就表现在主持词中。时代不断在进步,司仪等是很多场合都需...
美剧经典台词 美剧精选经典台词  在快速变化和不断变革的今天,能够利用到台词的场合越来越多,台词是一种特殊的,也是...
朗诵会主持词 关于朗诵会主持词4篇  主持词要根据活动对象的不同去设置不同的主持词。在当下这个社会中,很多场合都需...
记者节晚会主持词 记者节晚会主持词  主持词是主持人在台上表演的灵魂之所在。随着社会一步步向前发展,主持词的实用频率越...
婚礼父亲致辞 婚礼父亲致辞(精选15篇)  在平凡的学习、工作、生活中,大家肯定对各类致辞都很熟悉吧,致辞具有“礼...
校园红歌赛的主持词 校园红歌赛的主持词  主持词是主持人在节目进行过程中用于串联节目的串联词。在现今人们越来越重视活动氛...
开业主持词开场白 开业主持词开场白  根据活动对象的不同,需要设置不同的主持词。在当今社会生活中,活动集会越来越多,主...
关于唱歌比赛主持词   主持词是指主持人在主持节目的过程中进行节目串联的串联词,一般由开场白、中间部分与结束语组成。以下...