golang基础--reflect反射

匿名 (未验证) 提交于 2019-12-03 00:41:02

反射的知识点比较晦涩,后期会对此知识点展开深入的分析及示例代码展示

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

  • 反射使用TypeOf和ValueOf函数从接口中获取目标对象信息:字段属性,方法信息

    package main import (     "fmt"     "reflect" ) type User struct { //定义一个结构类型     Id   int     Name string     Age  int }  func (u User) Hello() { //定义一个结构方法     fmt.Println("Hello world") }  func Info(o interface{}) { //定义一个方法,参数为空接口     t := reflect.TypeOf(o)         //获取接收到的接口类型     fmt.Println("Type:", t.Name()) //获取名称      v := reflect.ValueOf(o) //获取接口的字段     fmt.Println("Fields:")      //获取结构字段     for i := 0; i < t.NumField(); i++ { //for循环,取出所拥有的字段         f := t.Field(i)               //获取值字段         val := v.Field(i).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)     }  }  func main() {     u := User{1, "OK", 12} //实例化一个结构     Info(u)                //调用Info函数  }  /*输出     Type: User     Fields:         Id:int=1       Name:string=OK        Age:int=12     Hello:func(main.User) */
  • 反射会将匿名字段作为独立字段(匿名字段本质)

    package main import (     "fmt"     "reflect" )  type User struct { //定义一个结构类型     Id   int     Name string     Age  int }  type Manager struct {     User  //嵌入User结构,User就是Manager结构的匿名字段     title string }  func main() {     m := Manager{User: User{1, "mm", 27}, title: "name"} //注意初始化方式     t := reflect.TypeOf(m)                               //传递结构      fmt.Printf("%#v\n", t.Field(0))                  //获取索引为0的字段信息,即User字段信息     fmt.Printf("%#v\n", t.FieldByIndex([]int{0, 0})) //根据索引取出ID的字段信息() } //{0,0}--User在Manager索引为0,ID在User索引为0  /*output     reflect.StructField{Name:"User", PkgPath:"", Type:(*reflect.rtype)(0x4ac220), Tag:"",     Offset:0x0, Index:[]int{0}, Anonymous:true}  "Anonymous:true" 其中包含Anonymous(匿名)字段 */
  • 想要利用反射修改对象状态,前提是interface.data是settable,即pointer-interface(指针接口)

    • 示例1
    //这是一个简单的修改对象状态 package main import (     "fmt"     "reflect" )  func main() {     x := 123                    //底层类型是int类型     v := reflect.ValueOf(&x)    //传递x的指针      v.Elem().SetInt(999)        //通过方法修改x变量的值      fmt.Println(x) }  /*输出 x--->  999 */
    • 示例2
    //通过反射修改结构字段 package main import (     "fmt"     "reflect" )  type User struct {     Name string     ID   int     Age  int }  func main() {     u := User{"MAOZI", 1, 22}     Set(&u)     fmt.Println(u)  }  func Set(o interface{}) {     v := reflect.ValueOf(o)      if v.Kind() != reflect.Ptr && !v.Elem().CanSet() { //判断是否为反射typestring,且可以被修改         fmt.Println("fuck")         return     } else { //如果条件都满足         v = v.Elem()     }      f := v.FieldByName("Name") //通过名字段名找字段     if !f.IsValid() {          //IsValid方法判断是否找了字段         fmt.Println("invalid")         return     }     if f.Kind() == reflect.String {         f.SetString("momo")     }  }  /*输出 {momo 1 22} */
  • 通过反射可以"动态"调用方法

    //通过反射动态调用结构方法 package main import (     "fmt"     "reflect" )  type User struct {     Name string     ID   int     Age  int }  func (u User) Hello(name string) {     fmt.Println("Hello", name, ",my name is", u.Name)  } func main() {     u := User{"Golang", 1, 22}     v := reflect.ValueOf(u)     mv := v.MethodByName("Hello") //反射:通过名字找结构字段信息      args := []reflect.Value{reflect.ValueOf("Python")}     mv.Call(args)  }  /*输出 Hello Python ,my name is Golang */

原文:https://www.cnblogs.com/failymao/p/9321189.html

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!