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)
}

相关内容

热门资讯

开业致辞 开业致辞(通用6篇)  在日复一日的学习、工作或生活中,大家或多或少都用到过致辞吧,致辞要求风格的雅...
80岁生日庆典主持词 80岁生日庆典主持词(精选5篇)  主持词可以采用和历史文化有关的表述方法去写作以提升活动的文化内涵...
感恩节活动主持词 2022年感恩节活动主持词  根据活动对象的不同,需要设置不同的主持词。在如今这个中国,我们对主持词...
电视剧《一起同过窗》经典的台... 电视剧《一起同过窗》经典的台词  在社会一步步向前发展的今天,很多情况下我们需要用到台词,台词是用以...
开门红主持词 开门红主持词  活动对象的不同,主持词的写作风格也会大不一样。在现在的社会生活中,主持人在活动中起到...
六一儿童节慰问活动致辞 六一儿童节慰问活动致辞(通用5篇)  在我们平凡的日常里,大家一定都接触过致辞吧,致辞具有有张有弛、...
生日主持词 关于生日主持词范文集锦五篇  主持词要注意活动对象,针对活动对象写相应的主持词。在当今社会生活中,司...
春晚节目主持人 临近春节,中央电视台毫无悬念地对外宣布70后吕逸涛,正式出任2016年猴年央视春晚总导演。消息公布后...
教师节领导简短致辞 教师节领导简短致辞(精选8篇)  在日常学习、工作和生活中,大家都不可避免地要接触到致辞吧,致辞讲求...
同学会主持词 【精华】同学会主持词(通用10篇)  主持词要根据活动对象的不同去设置不同的主持词。在当今社会生活中...
演讲比赛闭幕词 演讲比赛闭幕词范文(精选8篇)  要增加主持词的文化内涵,达到寓教于乐的主持词的写作,在不增加篇幅的...
学子宴主持词 学子宴主持词  各位女士、各位嘉宾、各位亲朋挚友,  合:大家好!  女:今日,初秋丽日,艳阳高照;...
晚会结束语主持词 晚会结束语主持词范文汇总5篇  主持词要把握好吸引观众、导入主题、创设情境等环节以吸引观众。在当今社...
南安市延平中学第三届教代会第... 南安市延平中学第三届教代会第三次会议闭幕词范文各位代表、同志们:  历时一天的南安市延平中学第三届教...
《老友记》经典台词 《老友记》经典台词集锦  She just graduated. 她刚毕业。  We don't h...
新上岗同事接风宴会上的致辞 新上岗同事接风宴会上的致辞  谢谢大家,我想说三句话。  第一句:热烈欢迎。今天宴会的主题是:为新参...
迎新晚会主持词 迎新晚会主持词范文(精选9篇)  主持词要把握好吸引观众、导入主题、创设情境等环节以吸引观众。在人们...
读书节主持词 读书节主持词(精选15篇)  主持词要注意活动对象,针对活动对象写相应的主持词。现今社会在不断向前发...
宫崎骏《起风了》动漫的经典台... 宫崎骏《起风了》动漫的经典台词  台词(part/dialog/line)是戏剧表演中角色所说的话语...
婚礼回门答谢宴主持词 婚礼回门答谢宴主持词  尊敬的各位领导、各位来宾、朋友们,  大家中午好!  阳光明媚,歌声飞扬,欢...