小工具知识网

当前位置: 首页 > 行业知识 > golang的反射探索

行业知识

golang的反射探索

2026-10-31 18:12:48 来源:互联网转载

1、golang��反射常用的场景

()

1》类型检查—通用类包或者函数的时候,在运行时可以动态的获取任意对象的类型信息

2》动态调用方法—运行时动态的选择使用哪个方法

()

3》结构体标签处理—结构体字段一般是通过tag来注解。运行时可以通过反射读取tag。常用于解析配置文件,处理json,映射tag到某个特定的键。

4》动态操作结构体字段—运行时动态填充数据或者从一些通用的数据结构中提取数据。

5》实现通用编程-比如通用的库

2、三大定律

1》将接口类型变量转换为反射对象

反射对象指的是:reflect.type-表示接口值的类型信息和reflect.value-表示接口值的具体值,两种类型。

var x float64 = 1.1v := x.reflect.ValueOf(x)//或者是typeOf()// v是x的反射对象

v.type() // 表示类型

v.kind() // 表示底层的实际类型

2》反射对象可以转换为接口类型

var x float64 = 3.4v := reflect.ValueOf(x) // v是x的反射对象y := v.Interface().(float64) // 结果是3.4

3》要修改反射对象的值,其值必须是可以被设置的。(地址是不能直接去修改对应值的)

vv := reflect.ValueOf(&x)vv.Elem().Set(reflect.ValueOf(111.11))fmt.Println(x)

3、反射的常用场景示例

结构体为例

1》获取变量和方法

var ss = Student {   Username:"aa",   Age:11,}typeS := reflect.TypeOf(ss)numField := typeS.NumField()for i:=0;ifield := typeS.Field(i)fmt.Printf("变量名:%s, 变量是否可见:%s, 变量的tag是:%s\n",field.Name, field.Anonymous, field.Tag)}return a+b}var ss = &Student {   Username:"aa",   Age:11,}var ss = &Student {Username:"aa",Age:11,}typeadd := reflect.TypeOf(ss.Add)for i:=0;ifmt.Printf("%s\n",typeadd.In(i).Kind())}for i:=0;ifmt.Printf("%s\n",typeadd.Out( i).Kind())}Color() string}type Child struct {}func (c *Child) Color() string {return "this is a child"}type Dog struct {}peopleType := reflect.TypeOf((*People)(nil)).Elem()fmt.Println("people is interface?", peopleType.Kind() == reflect.Interface)noPointChildType := reflect.TypeOf(Child{})pointChildType := reflect.TypeOf(&Child{})noPointDogType := reflect.TypeOf(Dog{})pointDogType := reflect.TypeOf(&Dog{})fmt.Println("nopoint child 是否实现了people接口:\n", noPointChildType.Implements(peopleType))fmt.Println("point child 是否实现了people接口:\n", pointChildType.Implements(peopleType))fmt.Println("nopoint dog 是否实现了people接口:\n", noPointDogType.Implements(peopleType))fmt.Println("nopoint dog 是否实现了people接口:\n", pointDogType.Implements(peopleType))/**输出结果如下:people is interface? truenopoint child 是否实现了people接口: falsepoint child 是否实现了people接口: truenopoint dog 是否实现了people接口: falsenopoint dog 是否实现了people接口: false*/Username:"miss zhao",}sValueOf := reflect.ValueOf(&s)fmt.Println(sValueOf.Elem().FieldByName("Username"))sTypeOf := sValueOf.Type()fmt.Println(sTypeOf)/**输出结果如下:miss zhao*main.Student*/Username:"miss zhao",}// 指针sValueOf := reflect.ValueOf(&s)// 非指针noPoint := sValueOf.Elem()//*main.Student main.Studentfmt.Println(sValueOf.Type(), noPoint.Type())//互转point := noPoint.Addr()//*main.Studentfmt.Println(point.Type())Username:"miss zhao",}sValueOf := reflect.ValueOf(&s)noPoint := sValueOf.Elem()// 转换为原始类型s = noPoint.Interface().(Student)fmt.Println(s.Username)}v := reflect.ValueOf(i)fmt.Println(v.Kind() == reflect.Invalid)// 判断是否nilvar ss *Student = nilv = reflect.ValueOf(ss)if v.IsValid(){fmt.Println(v.IsNil())}//只声明 所有的值都是零值var s Studentv = reflect.ValueOf(s)// 必须先判断isValidif v.IsValid() {fmt.Println(v.IsZero())}return a+b}// main函数里s := Student{Username:"miss zhao",}// 注意:使用指针可以调用指针和非指针的方法ss := reflect.ValueOf(&s)methodByName := ss.MethodByName("Add")resultSlice := methodByName.Call([]reflect.Value{reflect.ValueOf(1), reflect.ValueOf(2)})fmt.Println(resultSlice[0].Interface().(int))/**这里的输出结果如下:3*/

上一篇:揭秘流控背后的秘密,一文带你洞悉其奥秘!

下一篇:谷歌下载攻略揭秘,安全获取所需文件,避免违法犯罪风险!