• go的反射reflect


    我们项目中反射一般是在特定场合获取对象的信息, 然后动态调用对象方法 或者修改对象的属性,但是go里面还有指针【地址】一说法, 来看看是怎么用的

    package main
     
    import (
        "fmt"
        "reflect"
    )
     
    func main() {
        var x float64 = 3.4
        p := reflect.ValueOf(&x) // Note: take the address of x.
        /*为了得到 p 指向的数据,可以调用 Value 类型的 Elem 方法。
        Elem 方法能够对指针进行“解引用”,然后将结果存储到反射 Value 类型对象 v 中*/
        v := p.Elem()
        v.SetFloat(7.1)
        fmt.Println(x)
    }

    如果是常见的类型 struct又该如何了:

    package main

    import (
        "fmt"
        "reflect"
    )

    func main() {
        type T struct {
            A int
            B string `json:"b"`
        }
        t := T{23, "skidoo"}
        s := reflect.ValueOf(&t).Elem()
        ///获取反射信息
        typeOfT := s.Type()
        for i := 0; i < s.NumField(); i++ {
            f := s.Field(i)
            fmt.Printf("%d: %s %s = %v ", i,
                typeOfT.Field(i).Name, f.Type(), f.Interface())
        }
        // 通过字段名, 找到字段类型信息
        if bType, ok := typeOfT.FieldByName("B"); ok {
            // 从tag中取出需要的tag
            fmt.Printf("B has tag %s ", bType.Tag.Get("json"))
        }
        //修改对象数据
        s.Field(0).SetInt(77)
        s.Field(1).SetString("Sunset Strip")
        fmt.Println("t is now", t)
    }

    运行结果:

    0: A int = 23
    1: B string = skidoo
    B has tag b
    t is now {77 Sunset Strip}

     如果我们修改了程序让 s 由 t(而不是 &t)创建,程序就会在调用 SetInt 和 SetString 的地方失败,因为 t 的字段是不可设置的。

    普通方法的调用:

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    // 普通函数
    func add(a, b int) int {
        return a + b
    }
    func main() {
        // 将函数包装为反射值对象
        funcValue := reflect.ValueOf(add)
        // 构造函数参数, 传入两个整型值
        paramList := []reflect.Value{reflect.ValueOf(10), reflect.ValueOf(20)}
        // 反射调用函数
        retList := funcValue.Call(paramList)
        // 获取第一个返回值, 取整数值
        fmt.Println(retList[0].Int())
    }

    接口方法

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    type Table interface {
        TableName() string
    }
    
    type Cal interface {
        Add(a, b int) int
    }
    
    type model struct{}
    
    func (m model) TableName() string {
        return "table_name"
    }
    
    func (m model) Add(a, b int) int {
        return a + b
    }
    func main() {
        var mod model
        getTableName(mod)
    }
    
    /*
    reflect.New()函数的声明 func New(typ Type) Value
    根据传入的tpye,可以获取到对应的value
    */
    func getTableName(v interface{}) {
        rt := reflect.TypeOf(v)
        rv := reflect.ValueOf(v)
        if tabler, ok := rv.Interface().(Table); ok {
            fmt.Println(tabler.TableName())
        }
        if cal, ok := rv.Interface().(Cal); ok {
            fmt.Println(cal.Add(10, 20))
        }
        ///
        if tabler, ok := reflect.New(rt).Interface().(Table); ok {
            fmt.Println(tabler.TableName())
        }
        if cal, ok := reflect.New(rt).Interface().(Cal); ok {
            fmt.Println(cal.Add(20, 30))
        }
    }

    对象方法:

    package main

    import (
        "fmt"
        "reflect"
    )

    type Person struct {
        Name string
        Age  int
        Sex  string
    }

    //如果Tool小写后面就没办法反射
    type Tool struct {
        Cap string
        Key string
    }

    func (t Tool) Print() {
        fmt.Println("tool:" + t.Cap + t.Key)
    }

    func (p Person) PrintInfo(t *Tool) {
        t.Cap = "green"
        t.Key = "long"
        fmt.Printf("姓名:%s, 年龄:%s, 性别:%s, 参数tool内容:%s %s ", p.Name, p.Age, p.Sex, t.Key, t.Cap)
    }

    func main() {
        p1 := Person{"Rbuy", 20, "男"}
        ///调用person的PrintInfo 方法
        rtyp := reflect.TypeOf(p1)
        rcvr := reflect.ValueOf(p1)
        rmethod, ok := rtyp.MethodByName("PrintInfo")
        if ok {
            // 得到第一个此method第1参数的Type,第零个当然就是结构体本身了
            replyType := rmethod.Type.In(1).Elem()
            //实例化返回值的地址  *tool
            replyv := reflect.New(replyType)
            //rcvr 可以理解为对象实例  replyv 理解为返回值
            rmethod.Func.Call([]reflect.Value{rcvr, replyv})

            //调用tool的print
            var t Tool
            rtyp = reflect.TypeOf(t)
            rmethod, ok = rtyp.MethodByName("Print")
            if ok {
                rmethod.Func.Call([]reflect.Value{replyv.Elem()})
            }
        }

    }
  • 相关阅读:
    企业站前端——总结
    visual studio插件 visual assistx
    github 预览html
    Resharper
    c#解析json
    Visual Studio 2015 RC Downloads
    C#位运算讲解与示例
    java 位运算权限管控(转载)
    双机热备
    c# 代码执行时间
  • 原文地址:https://www.cnblogs.com/majiang/p/14173199.html
Copyright © 2020-2023  润新知