golang反射
反射类型与反射值
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(p1)
fmt.Println(v1)
fmt.Println(p1)
//详细操作:判断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)
//方法名和类型
//PrintInfo func(main.Person)
//Say func(main.Person, string)
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
}
通过下标去反射匿名函数
package main
import (
"fmt"
"reflect"
)
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})
age := v1.FieldByIndex([]int{0, 1})
fmt.Println(name) //猫咪
fmt.Println(age) //1
}
通过反射修改数值
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)
}