zoukankan      html  css  js  c++  java
  • golang基础--reflect反射

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

    • 反射可达大提高程序的灵活性,使得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
      ", f.Name, f.Type, val)
      	}
      	//通过接口获取结构的方法
      	for i := 0; i < t.NumMethod(); i++ {
      		m := t.Method(i)
      		fmt.Printf("%6s:%v
      ", 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
      ", t.Field(0))                  //获取索引为0的字段信息,即User字段信息
      	fmt.Printf("%#v
      ", 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
      */
      
  • 相关阅读:
    洛谷P2334
    线性基
    6.28 模拟赛解题报告
    左偏树
    哈夫曼树 Huffman
    CSP/NOIP 之前还需要学/复习的东西
    CF718C
    6.13 模拟赛结题报告
    关于模拟退火
    『笔记』网络流
  • 原文地址:https://www.cnblogs.com/failymao/p/9321189.html
Copyright © 2011-2022 走看看