前言大家好,我是码农,周五!之前学的都是正向定义变量,正向开发!但是有什么吗?方法可以反过来吗?根据变量获取类型等操作。来看看Go的反射!!!什么是反射?嗯……,意思相反,就是把事情颠倒过来。比如这么一段很简单的代码。varaint=3fmt.Println(a)我们当然知道变量a是int类型,但是反过来,程序怎么知道a是int类型呢???这个时候就需要反思了。示例代码v:=reflect.TypeOf(a)fmt.Println(v)两段代码合并为一个执行结果。第二次执行的第二行代码成功将变量a恢复为int类型。什么???你对我有什么用???,嗯。..说实话,我用的不多,但我一定要知道。反射(reflect包)在Go中,任何变量都有特定的类型和特定的值,像varaint=3,特定类型是int,特定值是3。因此,变量的特定类型属于reflect.Type,变量的具体取值属于reflect.Value。而Go提供了reflect.TypeOf来获取具体的类型。reflect.ValueOf获取具体值。TypeOfTypeOf方法可以获取变量的具体类型。有这样一个需求,定义一个函数,可以接收任意类型的数据,并通过反射打印出变量类型。示例代码functionfuncreflectType(xinterface{}){v:=reflect.TypeOf(x)fmt.Printf("你传入的变量类型是:%v\n",v)}mainfuncmain(){varaint=666varbfloat64=3.14varcstring="helloworld"vard[3]int=[3]int{1,2,6}vare[]int=[]int{1,2,6,88}varfmap[string]interface{}=map[string]interface{}{"Name":"张三","Age":18,}reflectType(a)reflectType(b)reflectType(c)reflectType(d)reflectType(e)reflectType(f)}执行结果为通过reflect.TypeOf方法完美解决了上述需求。TypeOf的名称和种类是什么意思?这更好地体现在结构上。简而言之,TypeOf的返回过于笼统,还有更详细的类型,可以通过这两个属性获取。示例代码functionfuncreflectType(xinterface{}){v:=reflect.TypeOf(x)fmt.Printf("你传入的变量类型是:%v|Name:%v|Kind:%v\n",v,v.Name(),v.Kind())}结构typeStudentstruct{NamestringAgeint}mainfuncmain(){varaintvarb*intvarc[]intvardmap[string]interface{}vareStudentreflectType(a)reflectType(b)reflectType(c)reflectType(d)reflectType(e)}执行结果总结经过对比,会发现几个比较特殊的问题。如果变量是指针类型,Name为空,Kind为ptr。如果变量是引用类型(slice和map)类型,Name为空,只有Kind。如果变量是结构,Name是结构的名称,Kind是结构。ValueOfTypeOf只能反向获取变量的具体类型,而不能获取具体的值,有点不厚道。所以ValueOf就是为了解决这个问题而来的,但是ValueOf的厉害之处在于它还包括变量类型。注意:ValueOf和TypeOf的Kind属性的返回内容是完全一样的。需求:定义一个可以接收任意类型的函数,通过反射获取变量类型和变量值。FunctionfuncreflectType(xinterface{}){v:=reflect.ValueOf(x)k:=v.Kind()switchk{casereflect.Int:fmt.Printf("我是Int类型,我的值为%v\n",v.Int())casereflect.Slice:fmt.Printf("我是切片类型,我的值为%v\n",v.Slice(1,2))casereflect.Map:fmt.Printf("我是slice类型,我的值为%v\n",v.MapKeys())//case:可以继续case}}mainfuncmain(){varaint=1varc[]int=[]int{1,5,7,19}vardmap[string]interface{}=map[string]interface{}{"Name":"Hello","Age":18,}vareStudentreflectType(a)reflectType(c)reflectType(d)reflectType(e)}执行结果通过反射设置值反射的另一个用途是动态修改变量值。你可能暂时没有意识到,但你仍然需要学习语法。通过反射设置值需要使用Elem方法,输入必须是指针。示例代码functionfuncreflectSetValue(xinterface{}){v:=reflect.ValueOf(x)//kind也必须是Elem调用vark=v.Elem().Kind()switchk{casereflect.Int://反射修改必须通过Elemv.Elem().SetInt(200)}}mainfuncmain(){varaint=10fmt.Printf("valueofa:%v\n",a)//反射修改值必须传入地址reflectSetValue(&a)fmt.Printf("valueofa:%v\n",a)}执行结果总结以上我们学习了Go基础反射的TypeOf,TypeOf的Name和Kind,ValueOf,以及通过反射设置值。其中,Kind有Type和ValueOf两种类型。通常,TypeOf和ValueOf一起使用会更好!反射可能不太容易看懂,所以一定要努力!坚持!!如果您在操作过程中有任何问题,记得在下方留言,我们看到问题会第一时间解决。周五我是码农,如果觉得还不错记得点个赞哦。感谢您的收看。本文转载自微信公众号《Go语言进阶学习》,可通过以下二维码关注。转载本文请联系Go语言进阶学习公众号。
