GO-反射
一、什么是反射
反射是程序在运行时检查、修改自身结构和行为的能力
在Go中,一切皆类型,反射也是一种类型
二、反射的两种基本类型(Value/Type)
//Type和Value是反射的两种基本类型
type Type interface {...}
type Value struct {...}
//构造函数:
func ValueOf(i interface{}) Value
func TypeOf(i interface{}) Type
//Value可以转换为Type类型:
func (v Value) Type() Type
三、Value.Type()/Kind()
通过反射获取value、type、kind
type Animal struct{
i int
j string
}
func main() {
num := Animal{1,"hello"}
ref := reflect.ValueOf(num)
fmt.Println(ref, ref.Type(), ref.Kind()) //{1 hello} main.Animal struct
}
四、Value.Interface()
转换类型必须与实际类型相符,否则panic
func main() {
a := 1
refA := reflect.ValueOf(a)
fmt.Printf("%T,%v\n", refA,refA) //reflect.Value,1
fmt.Printf("%T,%v\n", refA.Int(),refA.Int()) //int64,1
fmt.Printf("%T,%v\n", refA.Interface(),refA.Interface()) //int,1
//refA.Float()
//refA.String()
}
五、Value.Elem()
若反射中存储的是指针,通过Elem()间接访问值
func main() {
a := 1
b := &a
refA := reflect.ValueOf(b)
fmt.Println(refA) //0xc0000aa058
fmt.Println(refA.Elem()) //1
}
六、Value.Set()
动态修改反射的值
func main() {
a := 1
reflect.ValueOf(&a).Elem().SetInt(2) //必须传指针&a
fmt.Println(a) //2
}
七、结构体与反射
type User struct{
Id int
Name string
Age int
}
func (u User) Eat(){
fmt.Println("干饭了!")
}
func (u User) EatWhat(what string){
fmt.Printf("今天吃%s!\n", what)
}
func main() {
user1 := User{1,"大星",22}
//通过反射遍历结构体
ref := reflect.ValueOf(user1)
for i:=0;i<ref.Type().NumField();i++{
fieldName := ref.Type().Field(i).Name
fieldType := ref.Type().Field(i).Type
fieldValue := ref.Field(i).Interface()
fmt.Println(fieldName, fieldType, fieldValue) //(Id int 1) (Name string 大星) (Age int 22)
}
//通过反射修改结构体
ref1 := reflect.ValueOf(&user1).Elem()
ref1.Field(0).SetInt(333)
fmt.Println(user1) //{333 大星 22}
ref1.Field(0).Set(reflect.ValueOf(444))
fmt.Println(user1) //{444 大星 22}
//通过反射动态调用结构体方法
//无参数
method1 := ref.MethodByName("Eat")
args1 := make([]reflect.Value, 0)
method1.Call(args1) //干饭了!
//有参数
method2 := ref.MethodByName("EatWhat")
args2 := []reflect.Value{reflect.ValueOf("麻辣小龙虾")}
method2.Call(args2) //今天吃麻辣小龙虾!
}