• Golang 反射reflection


    反射reflection

    • 反射可大大提高程序的灵活性,使得interface{}有更大的发挥余地
    • 反射使用TypeOf和ValueOf函数从接口中获取目标对象信息
    • 反射会将匿名字段作为独立字段(匿名字段本质)
    • 想要利用反射修改对象状态,前提是interface.data是settable,即pointer-interface
    • 通过反射可以“动态”调用方法

    对某一个struct进行反射的基本操作

    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)         //反射使用 TypeOf 和 ValueOf 函数从接口中获取目标对象信息
    	fmt.Println("Type:", t.Name()) //调用t.Name方法来获取这个类型的名称
    
    	v := reflect.ValueOf(o) //打印出所包含的字段
    	fmt.Println("Fields:")
    	for i := 0; i < t.NumField(); i++ { //通过索引来取得它的所有字段,这里通过t.NumField来获取它多拥有的字段数量,同时来决定循环的次数
    		f := t.Field(i)               //通过这个i作为它的索引,从0开始来取得它的字段
    		val := v.Field(i).Interface() //通过interface方法来取出这个字段所对应的值
    		fmt.Printf("%6s:%v =%v
    ", f.Name, f.Type, val)
    	}
    	for i := 0; i < t.NumMethod(); i++ { //这里同样通过t.NumMethod来获取它拥有的方法的数量,来决定循环的次数
    		m := t.Method(i)
    		fmt.Printf("%6s:%v
    ", m.Name, m.Type)
    
    	}
    }
    func main() {
    	u := User{1, "Jack", 23}
    	Info(u)
    }
    
    

    判断传入的类型是否是我们想要的类型

    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)                  //反射使用 TypeOf 和 ValueOf 函数从接口中获取目标对象信息
    	fmt.Println("Type:", t.Name())          //调用t.Name方法来获取这个类型的名称
    	if k := t.Kind(); k != reflect.Struct { //通过kind方法判断传入的类型是否是我们需要反射的类型
    		fmt.Println("xx")
    		return
    	}
    	v := reflect.ValueOf(o) //打印出所包含的字段
    	fmt.Println("Fields:")
    	for i := 0; i < t.NumField(); i++ { //通过索引来取得它的所有字段,这里通过t.NumField来获取它多拥有的字段数量,同时来决定循环的次数
    		f := t.Field(i)               //通过这个i作为它的索引,从0开始来取得它的字段
    		val := v.Field(i).Interface() //通过interface方法来取出这个字段所对应的值
    		fmt.Printf("%6s:%v =%v
    ", f.Name, f.Type, val)
    	}
    	for i := 0; i < t.NumMethod(); i++ { //这里同样通过t.NumMethod来获取它拥有的方法的数量,来决定循环的次数
    		m := t.Method(i)
    		fmt.Printf("%6s:%v
    ", m.Name, m.Type)
    
    	}
    }
    func main() {
    	u := User{1, "Jack", 23}
    	Info(u)
    }
    
    

    反射 匿名或嵌入字段

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    type User struct {
    	Id   int
    	Name string
    	Age  int
    }
    
    type Manager struct {
    	User  //反射会将匿名字段作为一个独立字段来处理
    	Title string
    }
    
    func main() {
    	m := Manager{User: User{1, "Jack", 12}, Title: "123"}
    	t := reflect.TypeOf(m)
    	fmt.Printf("%#v
    ", t.Field(0))                   //#号会将reflect的struct的详情页打印出来,可以看出来这是一个匿名字段
    	fmt.Printf("%#v 
    ", t.FieldByIndex([]int{0, 0})) //此时 我们就可以将User当中的ID取出来,这里面需要传进方法中的是一个int类型的slice,User相对于manager索引是0,id相对于User索引也是0
    	fmt.Printf("%v 
    ", t.FieldByIndex([]int{0, 1}))
    	v := reflect.ValueOf(m)
    	fmt.Printf("%#v
    ", v.Field(0))
    }
    
    

    通过反射修改struct中的内容

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    func main() {
    	x := 123
    	v := reflect.ValueOf(&x)   
    	//传递指针才能修改
    	v.Elem().SetInt(999)
    	fmt.Println(x)
    }
    PS G:mygosrcmytest> go run .	emp10.go
    999
    
    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    type User struct {
    	Id   int
    	Name string
    	Age  int
    }
    
    func main() {
    	u := User{1, "Tom", 12}
    	Set(&u)
    	fmt.Println(u)
    
    }
    
    func Set(o interface{}) {
    	v := reflect.ValueOf(o)
    	if v.Kind() == reflect.Ptr && !v.Elem().CanSet() {
    		fmt.Println("xxx")
    		return
    	} else {
    		v = v.Elem()
    	}
    	f := v.FieldByName("Name")
    	if !f.IsValid() {
    		fmt.Println("xiugaishibai")
    	}
    	if f.Kind() == reflect.String {
    		f.SetString("jACK")
    	}
    
    }
    
    

    通过发射进行方法的调用 动态调用方法

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    type User struct {
    	Id   int
    	Name string
    	Age  int
    }
    
    func (u User) Hello(name string) {
    	fmt.Println("Hello", name, "My name is", u.Name)
    }
    
    func main() {
    	u := User{1, "OK", 12}
    	v := reflect.ValueOf(u)
    	mv := v.MethodByName("Hello")
    	args := []reflect.Value{reflect.ValueOf("JOE")}
    	mv.Call(args)
    }
    
    
  • 相关阅读:
    HDFS Namenode 高可用
    旁路模式,numa、mmu、调整内存分页大小
    k8s 调度 GPU
    破解 CSDN 登录后才能复制
    微信小程序开发video遮罩功能(禁止拖动进度条)
    微信小程序之下拉刷新
    微信小程序JS中文排序
    vue2 和 vue3 路由使用对比
    Golang 操作mongo
    win10安装CUDA和cuDNN的正确姿势
  • 原文地址:https://www.cnblogs.com/skymyyang/p/7690837.html
Copyright © 2020-2023  润新知