go语言基础 反射 reflect

反射reflect
struct
reflect.TypeOf(i interface{})-->Type
获取结构体的字段的类型,字段名

方法的类型,方法的名字

package main

import (
   "fmt"
   "reflect"
)

type Person struct {
   Name string
   Age int
   Sex string
}

func (p Person)Say(msg string)  {
   fmt.Println("hello,",msg)
}
func (p Person)PrintInfo()  {
   fmt.Printf("姓名:%s,年龄:%d,性别:%s\n",p.Name,p.Age,p.Sex)
}

func main()  {
   //1.创建一个struct的对象
   p1 := Person{"王二狗",30,"男"}
   //1.第一部分:通过反射操作结构体中的字段:获取字段的类型,名称,数值。。
   //通过reflect包下的TypeOf(),获取p1的类型

   t1:=reflect.TypeOf(p1)
   fmt.Println(t1) //main.Person
   fmt.Println(t1.Name()) //Person
   fmt.Println(t1.Kind()) //struct
   //通过reflect包下ValueOf(),获取p1的值
   v1:=reflect.ValueOf(p1) //{王二狗 30 男}
   fmt.Println(v1)

   //详细操作:判断t1的种类是结构体类型
   if t1.Kind() == reflect.Struct{
      //获取字段的数量
      count:=t1.NumField() //3个字段
      fmt.Println(count)

      for i:=0;i<count;i++{
         filed:=t1.Field(i)
         val:=v1.Field(i).Interface()//根据v1获取对应字段的数值,--->空接口类型
         //fmt.Println(filed)
         fmt.Println("字段名称:",filed.Name,"字段类型:",filed.Type,"字段数值:",val)
      }
   }


   //2.通过反射,操作方法
   fmt.Println(t1.NumMethod())
   for i:=0;i<t1.NumMethod();i++{
      method:=t1.Method(i)
      fmt.Println(method.Name,method.Type)
   }

   //执行方法
   m1:=v1.MethodByName("PrintInfo")
   m1.Call(nil)//执行m1对应的PrintInfo()

   m2:=v1.MethodByName("Say")
   m2.Call([]reflect.Value{reflect.ValueOf("你好啊")}) // string-->Value

}

reflect.ValueOf(i interface{})-->Value
获取结构体的字段的数值

获取方法的对象--->Call(),执行对应的方法

package main

import (
   "reflect"
   "fmt"
)

type Animal struct {
   Name string
   Age  int
}

type Cat struct {
   Animal
   Color string
}

func main() {
   c1 := Cat{Animal{"猫咪", 1}, "白色"}

   t1 := reflect.TypeOf(c1)
   fmt.Println(t1.NumField())

   for i := 0; i < t1.NumField(); i++ {
      field := t1.Field(i)
      fmt.Println(field)
   }

   //获取匿名字段
   /*
   匿名字段,可以通过下标获取
   FieldByIndex([]int{0})-->Animal
   FieldByIndex([]int{0,0})-->Animal中的第一个字段:Name
    */
   f1:=t1.FieldByIndex([]int{0,0})
   fmt.Println(f1.Name,f1.Type)//Name string
   f2:=t1.FieldByIndex([]int{0,1})
   fmt.Println(f2.Name,f2.Type)


   v1:=reflect.ValueOf(c1)

   name:=v1.FieldByIndex([]int{0,0})
   fmt.Println(name)
}

//匿名字段
t1.FieldByIndex([]int{0,0})
v1.FieldByIndex([]int{0,0})
//更改数据
reflect.ValueOf(p1)-->value
reflect.Struct
reflect.ValueOf(&p1)-->value
reflect.Ptr
v1 = v1.Elem()
CanSet()-->bool
c1.FieldByName()-->f1

f1.SetXXX(新value)

package main

import (
   "reflect"
   "fmt"
)

type Student struct {
   Name string
   Age int
   School string
}
func main()  {
   /*
   通过反射,来更改对象的数值:前提是数据可以被更改
    */
    s1:=Student{"王二狗",19,"新东方"}
    fmt.Printf("%T\n",s1) //main.Student
    p1:=&s1
    fmt.Printf("%T\n",p1) //*main.Student
    fmt.Println(s1.Name)
    fmt.Println((*p1).Name,p1.Name)


    v1:= reflect.ValueOf(&s1) // value

    if v1.Kind()==reflect.Ptr{
      fmt.Println(v1.Elem().CanSet())
      v1 = v1.Elem()
    }

    f1:=v1.FieldByName("Name")
    f1.SetString("王三狗")
    f3:=v1.FieldByName("School")
    f3.SetString("蓝翔学校")
    fmt.Println(s1)




}

猜你喜欢

转载自blog.csdn.net/weixin_42100098/article/details/80150088