美文网首页
第八节反射reflection

第八节反射reflection

作者: barriers | 来源:发表于2019-12-29 13:56 被阅读0次

    1.基本概念

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

    值和方法反射

    import (
        "fmt"
        "reflect"
    )
    
    type User struct {
        ID int
        Name string
        Age int
    }
    
    func (u User) Hello(){
        fmt.Println("Hello world")
    }
    
    func main()  {
        u := User{1, "雪飞霜", 18}
        Info(u)
    }
    
    func Info(o interface{}){
        t := reflect.TypeOf(o)
        fmt.Println("Type:", t.Name())
    // 判断是否是指针类型,是指针类型直接结束运算
        if k:= t.Kind();k!=reflect.Struct{
            fmt.Println("XX")
            return
        }
        v := reflect.ValueOf(o)
        fmt.Println("Fields:")
        //获取某个对象的字段信息及类型信息及其值
        for i:=0;i<t.NumField();i++{
            f:=t.Field(i)
            val := v.Field(i).Interface()
            //printf要在需要格式化的地方输出,其他直接输出变量或者直接输出字符串的可以直接用println
            fmt.Printf("%6s: %v = %v\n", f.Name, f.Type, val)
        }
        // 获取对象的方法信息
        for i:=0; i<t.NumMethod();i++{
            m:=t.Method(i)
            fmt.Printf("%6s: %v\n", m.Name, m.Type)
        }
    }
    

    匿名字段中的信息获取

    import (
        "fmt"
        "reflect"
    )
    
    type User struct {
        ID int
        Name string
        Age int
    }
    
    type Manger struct {
        User
        title string
    }
    
    func (u User) Hello(){
        fmt.Println("Hello world")
    }
    
    func main()  {
    
        m := Manger{User: User{1, "毒士", 12}, title: "贾诩"}
        t := reflect.TypeOf(m)
     // 取匿名字段信息(下标为0的为User类型的字段)
        fmt.Printf("%#v\n", t.Field(0))
    // 取非匿名字段信息(小标为1的title)
        fmt.Printf("%#v\n", t.Field(1))
        // 获取匿名字段中的Id信息(下标为0的字段的下标为0的字段)
        fmt.Printf("%#v\n", t.FieldByIndex([]int{0,0}))
    }
    

    用reflect修改一个整形的值

    通过反射对接口中的对象的值进行修改

    import (
        "fmt"
        "reflect"
    )
    
    func main()  {
    
        m := 123
     //必须传入指针,否则修改不了值
        v := reflect.ValueOf(&m)
     //修改为999
        v.Elem().SetInt(999)
     //输出为999
        fmt.Printf(x)
    }
    

    用reflect修改一个基本类型的值

    通过反射对接口中的对象的值进行修改

    import (
        "fmt"
        "reflect"
    )
    
    type User struct {
        ID int
        Name string
        Age int
    }
    
    func (u interface{}) Set(){
        v := reflect.ValueOf(u)
        // 判断对象是不是pointer-interface并且是可设值的
        if v.Kind()==reflect.Ptr&&!v.Elem().CanSet(){
            fmt.Println("XXX")
            return
        } else {
            // 因为都是value类型的,所以可以直接赋值
            v = v.Elem()
        }
        // 通过字段名字取值
        if f:=v.FieldByName("Name");f.Kind()==reflect.String{
            f.SetString("BYBYBY")
        }
        
        fmt.Println("Hello world")
    }
    
    func main()  {
        m := User{1, "孙鲁班", 12}
        Set(&m)
        fmt.Printf(m)
    }
    

    根据不确定的属性修改值

    通过反射对接口中的对象的值进行修改
    通过sValid判断是否有该属性

    import (
        "fmt"
        "reflect"
    )
    
    type User struct {
        ID int
        Name string
        Age int
    }
    
    func (u interface{}) Set(){
        v := reflect.ValueOf(u)
        // 判断对象是不是pointer-interface并且是可设值的
        if v.Kind()==reflect.Ptr&&!v.Elem().CanSet(){
            fmt.Println("XXX")
            return
        } else {
            // 因为都是value类型的,所以可以直接赋值
            v = v.Elem()
        }
        // 通过字段名字取值
        f:=v.FieldByName("Name")
        // 判断结构体中是否有该字段,没有则返回,有则修改值
        if !f.IsValid(){
            fmt.Println("BAD")
            return
        }
        if f.Kind()==reflect.String{
            f.SetString("BYBYBY")
        }
        
        fmt.Println("Hello world")
    }
    
    func main()  {
        m := User{1, "孙鲁班", 12}
        Set(&m)
        fmt.Printf(m)
    }
    

    通过反射动态调用方法

    正常调用

    import (
        "fmt"
        "reflect"
    )
    
    type User struct {
        ID int
        Name string
        Age int
    }
    
    func main()  {
        u := User{1, "雪飞霜", 18}
        u.HelloUser("alice")
    }
    
    func (u User) HelloUser(name string){
        fmt.Println("Hello", name, "my name is", u.Name)
    }
    

    反射调用

    import (
        "fmt"
        "reflect"
    )
    
    type User struct {
        ID int
        Name string
        Age int
    }
    
    func main()  {
        u := User{1, "雪飞霜", 18}
        v := reflect.ValueOf(u)
        mv := v.MethodByName("HelloUser")
        args := []reflect.Value{reflect.ValueOf("alice")}
        mv.Call(args)
    }
    
    func (u User) HelloUser(name string){
        fmt.Println("Hello", name, "my name is", u.Name)
    }
    

    练习

    定义一个结构,通过反射来打印其信息,并调用方法,获取方法返回值,并对返回值进行其他操作。

    相关文章

      网友评论

          本文标题:第八节反射reflection

          本文链接:https://www.haomeiwen.com/subject/sugsoctx.html