反射基本介绍:@H_301_5@
(1)反射可以在运行时动态获取变量的各种信息,比如变量的类型、类别;@H_301_5@
(2)如果是结构体变量,还可以获取结构体本身的信息(包括结构体字段、方法);@H_301_5@
(3)通过反射,可以修改变量的值,可以调用关联的方法;@H_301_5@
(4)使用反射,需要import "reflect:"@H_301_5@
变量--空接口--relect.Value之间的转换关系:@H_301_5@
@H_301_5@@H_301_5@
int变量与反射变量之间的转换:@H_301_5@
package mainimport ( "fmt" reflect")func reflectTest(b interface{}) { rTyp := reflect.TypeOf(b) fmt.Printf(rTyp=%v,type=%T\n,rTyp,rTyp) rVal := reflect.ValueOf(b) fmt.Printf(rVal=%v,rVal,rVal) iVal := rVal.Interface() num2 := iVal.(int) fmt.Printf(num2=%v,num2,num2)}func main() { var num int = 100 reflectTest(num)}
@H_301_5@@H_301_5@
结构体变量与反射变量之间的转换:@H_301_5@
type student struct { name string age }func reflectTest02(b rVal.Interface() stu2 := iVal.(student) fmt.Printf(stu2=%v,stu2,stu2) fmt.Printf(name:%v,age:%v student{ name: tom20@H_301_5@@H_301_5@
反射注意事项和使用细节:
(1)reflect.Vale.Kind,获取变量的类别,返回的是一个常量;@H_301_5@@H_301_5@@H_301_5@
(2)Type是类型,Kind是类别,Type和Kind可能是相同的,也可能是不同的;@H_301_5@
比如:var num int=10的type是Int,Kind也是int@H_301_5@
var stu Student, stu的rype是pkg1.Student,Kind是struct@H_301_5@
(3)通过反射介意让变量在interface{}和reflect.Value之间相互转换;@H_301_5@
(4)使用反射的方式来获取变量的值,要求数据类型匹配;@H_301_5@
(5)通过反射来修改变量,注意当使用SetXxx方法来设置需要通过对指针类型来完成,这样才能改变传入变量的值,同时需要使用到reflect.Value.Elem()方法;即rVal.Elem().SetInt(20)@H_301_5@
具体实践;@H_301_5@
使用反射来遍历结构体的字段,并调用结构体的方法,并获取结构体标签的值。@H_301_5@
)type monster { name string `Json:name` Age int `Json:monster_age` score float32 Sex }func (m monster) Print() { fmt.Println(----strat----) fmt.Println() fmt.Println(----end----)}func (m monster) GetSum(n1,n2 int) { return n1 + n2}func (m monster) Set(name string,age int,score float32,sex ) { m.name = name m.Age = age m.score = score m.Sex = sex}func testStruct(b {}) { //获得类型 rtyp := reflect.TypeOf(b) 获得值 rval := reflect.ValueOf(b) 获得类别 kd := rval.Kind() 如果kd不是指针类型且rval.Elem()不是结构体类别 if kd != reflect.Ptr && rval.Elem().Kind() == reflect.Struct { fmt.Println(expect struct) return } 获取结构体有几个字段 num := rval.Elem().NumFIEld() fmt.Printf(struct has %d fIElds\n遍历每个字段 for i := 0; i < num; i++ { 输出该字段的值 fmt.Printf(fIEld %d:值为=%v\n获取该字段的Json标签 tagval := rtyp.Elem().FIEld(i).Tag.Get(Json如果标签不为空,则打印出标签 if tagval != "" { fmt.Printf(fIEld %d:tag为=%v\n0).SetString(孙悟空) 获取结构体有几个方法 numOfMethod := rval.Elem().NumMethod() fmt.Printf(struct has %d methods\n获取第二个方法,函数的顺序是按首字母的ACSII进行排序的,所以这里第二个方法是Print rval.Elem().Method(1).Call(nil) 定义一个reflect.Value切片 var params []reflect.Value 添加两个整型 params = append(params,reflect.ValueOf(10)) 40调用第一个方法,并传入参数(注意参数类型是reflect.Value切片) res := rval.Elem().Method(0).Call(注意res是一个切片,里面只有一个值 fmt.Println(res=",res[0].Int())}func main() { var a monster = monster{ name: 40020.9a) fmt.Println(a)}要在反射中修改结构体的字段的值,必须传入的是地址,并且在反射中使用.Elem().SetXxx()@H_301_5@
@H_301_5@@H_301_5@
具体实践2:通过反射完成适配器@H_301_5@
func main() { test1 := func(v1 ) { fmt.Printf(v1=%d,v2=%d\n= func(call interface{},args ...{}) { 获取参数长度 n := len(args) 定义参数切片 params := make([]reflect.Value,n) 将参数存入到切片中 0; i < n; i++ { params[i] = reflect.ValueOf(args[i]) } for i := 0; i < n; i++ { fmt.Println(args[i]) } 获取函数名 function := reflect.ValueOf(call) 将参数传给函数,并调用函数 function.Call() } brIDge(test1,1,2) brIDge(test2,1)">2,1)">test2)}运行结果:@H_301_5@
@H_301_5@@H_301_5@
具体实践3:通过反射 *** 作任意结构体类型@H_301_5@
type user { UserID name }func testReflectStruct() { var ( model *user sv reflect.Value ) model = &user{} sv = reflect.ValueOf(model) 这里是指针类别 fmt.Println(sv.Kind().String()) sv = sv.Elem() 这里是结构体类别 fmt.Println(sv.Kind().String()) sv.FIEldByname(UserID").SetString(1) sv.FIEldByname(name) fmt.Println(model)}@H_301_5@@H_301_5@
@H_301_5@
@H_301_5@ 总结
以上是内存溢出为你收集整理的(四十五)golang--反射全部内容,希望文章能够帮你解决(四十五)golang--反射所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)