Go编程基础-反射 reflection

首先来了解一下使用反射的好处:

-- 反射可大大提高程序的灵活性,使得interface{}有更大的发挥余地

--反射使用TypeOf()和ValueOf(函数从接口中获取目标对象的信息)

-- 反射会将匿名字段作为独立字段(匿名字段本质)

--想要利用反射修改对象的状态,前提是interface.data是settable,即pointer-interface

--通过反射可以动态地调用方法

然后让我们用一段代码,了解一下:

package main

import (
   "fmt"
   "reflect"
)

type User struct {
   Id int
   Name string
   Age int

}
func (u User) ReflectCalL(name string ,age int){
   fmt.Println(name,age,u.Name)
}
func (u User) ReflectCallno(){
   fmt.Println("hello,world")
}
func main() {
   //reflect的基本功能TypeOf和ValueOf
   var num float64 = 1.2345
   fmt.Println("type=",reflect.TypeOf(num))         // TypeOf用来动态获取输入参数接口中的值的类型,如果接口为空则返回nil
   fmt.Println("value=",reflect.ValueOf(num))        //ValueOf用来获取输入参数接口中的数据的值,如果接口为空则返回0
   //从relfect.Value中获取接口interface的信息
   //已知原有类型【进行“强制转换”】  realValue := value.Interface().(已知的类型)
   pointer := reflect.ValueOf(&num)     //传递一个地址
   value :=reflect.ValueOf(num)     //传递一个值
   converpointer:=pointer.Interface().(*float64)   
   convervalue := value.Interface().(float64)
   fmt.Println(converpointer)
   fmt.Println(convervalue)

 u:=User{1,"joy",13}
   //未知原有类型【遍历探测其Filed】
 info(u)
 //通过reflect.Value设置实际变量的值
   newValue :=pointer.Elem()
   newValue.SetFloat(2.3456)
   fmt.Println("newValue=",num)
   //通过reflect.ValueOf来进行方法的调用
 getValue :=reflect.ValueOf(u)   //要通过反射来调用起对应的方法,必须要先通过reflect.ValueOf(interface)来获取到reflect.Value,得到“反射类型对象”后才能做下一步处理
 method:=getValue.MethodByName("ReflectCalL")  //指定准确方法的名字,否则会panic
 args :=[]reflect.Value{reflect.ValueOf("cc"),reflect.ValueOf(34)}   //准备需要的参数切片
 method.Call(args)    传参调用方法
//调用没有参数的方法
 method1:=getValue.MethodByName("ReflectCallno")
 args1:=make([]reflect.Value,0)    
 method1.Call(args1)
   }
func info(o interface{}){     //接受一个空接口,任何一个结构体都可以看成一个空接口
   t :=reflect.TypeOf(o)      //先获取接口的reflect.Type
   fmt.Println(t)
   fmt.Println("Type:",t.Name())
   v :=reflect.ValueOf(o)    //获取接口中所有的值
   fmt.Println(v)
   fmt.Println("Fileds")
   for i:=0;i<t.NumField();i++{   通过NumFiled()获得字段的个数
      f :=t.Field(i)     
      val :=v.Field(i).Interface()   使用Interface()得到对应的值
      fmt.Printf("%6s: %v = %v\n",f.Name,f.Type,val)
   }
   for i:=0;i<t.NumMethod();i++{    //获得所有方法的数目
      m:=t.Method(i)
      fmt.Printf("%6s: %v\n",m.Name,m.Type)   //方法名和类型
   } 
结果:


说明:
  1. 转换的时候,如果转换的类型不完全符合,则直接panic,类型要求非常严格!
  2. 转换的时候,要区分是指针还是值
  3. 也就是说反射可以将“反射类型对象”再重新转换为“接口类型变量”

 

总结:今天刚看到反射这个概念的时候,感觉有点懵,后来把所有代码都打了一遍,把一部分都输出了解之后,才感觉懂了许多,所以还是要多加练习,熟能生巧嘛

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值