main.go
// Go语言·反射
package main
import (
model "day33/model"
)
var content string = `
————————————————Go语言·反射————————————————————
一、反射
应用场景:
结构体tag——对结构体序列化
编写函数的适配器,桥连接
介绍:
反射可以在运行时动态获取变量的各种信息。
比如:变量的类型type,类别kind
结构体变量,可以获取到结构体本身的信息
包含结构体的字段、方法
通过反射,可以修改变量的值,可以调用关联的方法
使用反射:import "reflect"
1.reflect.TypeOf(变量名),获取变量的类型,返回reflect.Type类型
2.reflect.ValueOf(变量名),可以获取变量的值,返回reflect.Value类型的结构体
通过reflect.Value,可以获取到关于该变量的很多信息。
二、注意事项
1.reflect.Value.Kind 获取变量类别,返回一个常量
2.Type是类型,Kind是类别,Type和Kind可能是相同的,
也可能是不相同的
比如:var num int = 10 num的Type是int,Kind也是int
比如:var stu Student
stu的Type是main.Student或model.Student
stu的Kind是Student
3.通过反射可以让变量在interface{}和reflect.Value之间相互转换
变量<=>interface{}<=>reflect.Value
4.使用反射的方式获取变量的值并返回对应的类型,必须数据类型匹配
比如:var x int = 10
应该用 reflect.Value(x).Int() 而不能用其他的,否则报panic
5.通过反射的来修改变量,注意当使用SetXxx方法来设置需要通过对应的
指针来完成,这样才能改变传入的变量的值。同时需要使用到reflect.Value.Elem()
reflectVal := reflect.ValueOf(b)
reflectVal.Elem().SetInt(100)
6.func (v Value) Elem() Value
Elem返回v持有的接口保管的值的Value封装,或者v持有的指针指向的值的Value封装。
如果v的Kind不是Interface或Ptr会panic;如果v持有的值为nil,会返回Value零值。
三、反射的最佳实践
1.使用反射来遍历结构体的字段,调用结构体的方法,并获取结构体标签的值
`
func main() {
model.Go()
}
model/utils.go
package model
import (
"fmt"
"reflect"
)
type Student struct {
Name string
Age int
}
func Going(){
var num int = 10
reflectModifyBaseDta(&num)
fmt.Println("num=",num)
}
// 基本数据类型<=>interface{}<=>reflect.Value
// var num int = 100
// reflectBaseDta(num)
func reflectBaseDta(b interface{}) {
// 通过反射获取传入的变量的type,kind,值
// 1.获取到 reflect.Type 类型
reflectType := reflect.TypeOf(b)
// reflectType的值:int,reflectType的类型:*reflect.rtype
fmt.Printf("reflectType的值:%v,reflectType的类型:%T \n",
reflectType,reflectType)
// 2.获取到 reflect.Value 类型
reflectVal := reflect.ValueOf(b)
// reflectVal的值:100,reflectVal的类型:reflect.Value
fmt.Printf("reflectVal的值:%v,reflectVal的类型:%T \n",
reflectVal,reflectVal)
// 3.将reflectVal---》转成 interface{}
interfaceVal := reflectVal.Interface()
// 4.通过断言--》int数据类型
intVal := interfaceVal.(int)
// intVal的值:100,intVal的类型:int
fmt.Printf("intVal的值:%v,intVal的类型:%T \n",
intVal,intVal)
}
/**
* [reflectStructDta ]
* 结构体<=>interface{}<=>reflect.Value
* @author Jhou Shuai
* @datetime 2019-06-12T14:57:45+0800
* stu := Student {
Name:"Faker",
Age:19,
}
reflectStructDta(stu)
*/
func reflectStructDta(b interface{}) {
// 1.获取到 reflect.Type 类型
reflectType := reflect.TypeOf(b)
// reflectType的值:model.Student,reflectType的类型:*reflect.rtype
fmt.Printf("reflectType的值:%v,reflectType的类型:%T \n",reflectType,reflectType)
// 2.获取到 reflect.Value 类型
reflectVal := reflect.ValueOf(b)
// reflectVal的值:{Faker 19},reflectVal的类型:reflect.Value
fmt.Printf("reflectVal的值:%v,reflectVal的类型:%T \n",reflectVal,reflectVal)
// 通过反射获取传入的变量的type,kind,值
// 1.reflectType.Kind() ===>
// 2.reflectVal.Kind() ===>
fmt.Printf("变量的kind:%v,reflectType的类型:%T \n",reflectType.Kind(),reflectType)
// 3.将reflectVal---》转成 interface{}
interfaceVal := reflectVal.Interface()
// interfaceVal的值:{Faker 19},interfaceVal的类型:model.Student
fmt.Printf("interfaceVal的值:%v,interfaceVal的类型:%T \n",interfaceVal,interfaceVal)
// 4.通过断言--》结构体
// switch interfaceVal.(type) {
// case
// }
structDta,ok := interfaceVal.(Student)
if ok{
fmt.Printf("structDta.Name的值:%v \n",structDta.Name)
}
}
/**
* [reflectModifyDta 修改值]
* @author Jhou Shuai
* var num int = 10
reflectModifyBaseDta(&num)
fmt.Println("num=",num)
* @datetime 2019-06-12T18:13:37+0800
*/
func reflectModifyBaseDta(b interface{}){
reflectVal := reflect.ValueOf(b)
// reflectVal的值:0xc00006a080,
// reflectVal的类型:reflect.Value,
// reflectVal的类别:ptr
fmt.Printf("reflectVal的值:%v,reflectVal的类型:%T,reflectVal的类别:%v \n",reflectVal,reflectVal,reflectVal.Kind())
reflectVal.Elem().SetInt(100)
}
/**
* [TypeJudge 类型断言]
* @author Jhou Shuai
* @datetime 2019-06-12T15:11:32+0800
*/
func TypeJudge(items ...interface{}) {
for index ,value := range items {
switch value.(type){
case bool:
fmt.Printf("第%v个参数是bool类型,值:%v \n",index,value)
case float32:
fmt.Printf("第%v个参数是float32类型,值:%v \n",index,value)
case int,int8,int16,int32,int64:
fmt.Printf("第%v个参数是整数类型,值:%v \n",index,value)
case string:
fmt.Printf("第%v个参数是string类型,值:%v \n",index,value)
case Student:
fmt.Printf("第%v个参数是Student类型,值:%v \n",index,value)
case *Student:
fmt.Printf("第%v个参数是*Student类型,值:%v \n",index,value)
default:
fmt.Printf("第%v个参数是类型不确定,值:%v \n",index,value)
}
}
}
网友评论