go语言反射

作者: 程序员小饭 | 来源:发表于2019-07-18 15:59 被阅读0次

    反射的特点

    • 反射功能具有强大的功能
    • 反射是用程序检查其所拥有的结构,尤其是类型的一种能力
    • 是元编程的一种形式
    • 我们可以在【运行时】通过反射来分析一个结构体
    • 检查其类型和变量(类型和取值)和方法
    • 动态的修改变量和调用方法
    • 这对于没有源代码的包尤其有用
    • 这是一个强大的工具,除非真的有必要,否则应当避免使用或者小心使用

    反射API

    TypeOf

    oType := reflect.TypeOf(obj)
    t.Name()
    kind := oType.Kind()
        kind:struct 系统类型的枚举
        type: 具体的类
    t.NumField()
    t.NumMethod()
    structField := oType.Field(i)
        structField.Name
        structField.Type
    
    method := oType.Method(i)
        methodType := methodType
            argNum := method.Type.NumIn()  参数个数
            artType := method.Type.In(0)  第1个参数类型
    t.FieldByIndex([]int{0, 1})
        找出第0个父结构体中的第1个属性
    

    ValueOf

    oValue := reflect.ValueOf(obj)
    field := oValue.Field(i) -> fieldValue :=value.Field(i).Interface{}(获取第i个属性的值的“正射”形式)

    fieldValue := value.FieldByIndex([]int{0, 0}).Interface()  找出第0个父结构体中的第0个属性值
    
    
    oPtrValue.Elem() 获取地址value中的值value
    
    oPtrValue.Elem().CanSet()  检查当前地址value内的值是否可以改变(可改变条件:可寻址+不来字非导出字段)
    
     oPtrValue.Elem().SetInt(999)
    
     value.SetString("jack")
    
     nameValue := value.FieldByName("Name")
    
    
     isVaild := value.IsVaild()  nil(0值)非法  非常罕见
    
     kind := value.Kind()和type.Kind()一样
     mathod := oValue.Method(i)   通过方法的值可以调取方法
     methodValue.Call([]reflect.Value{val1,val2})
    

    代码实例(简单类型的反射操作)

    package main
    import (
        "fmt"
        "reflect"
    )
    //简单类型的反射
    func reflectTest01(b interface{}) {
        //通过反射来获取传入变量的   type,kind。值
        //1.先获取到reflect.Type
        rType := reflect.TypeOf(b)
        fmt.Println("rType = ", rType)
        //2.获取到reflect.Value
        rVal := reflect.ValueOf(b)
        n2 := 2 + rVal.Int()
    
        fmt.Println("n2 = ", n2)
        fmt.Printf("rVal = %v, rVal type=%T\n", rVal, rVal)
        //下面我们将rVal转换成interface
        iv := rVal.Interface()
        //将interface通过断言转换成需要的类型
        num2 := iv.(int)
        fmt.Println("num2 = ", num2)
    }
    
    //复杂类型的反射
    func reflectTest02(b interface{}) {
        //通过反射获取到传入变量的type  kind值
        rType := reflect.TypeOf(b)
        fmt.Println("rType =", rType)
    
        //获取到reflectValue
        rVal := reflect.ValueOf(b)
    
        //获取变量对应的kind
        typeKind := rType.Kind()
        valKind := rVal.Kind()
        fmt.Printf("typeKind = %v, valKind = %v\n", typeKind, valKind)
    
        //将rVal转换为interface{}
        iv := rVal.Interface()
        fmt.Printf("iv = %v is type =%T\n", iv, iv)
        //把interface{}通过断言转换成需要的类型
        stu, ok := iv.(Student)
        if ok {
            fmt.Println("stu.Name = ", stu.Name)
        }
    }
    func changeValue(b interface{}) {
        rVal := reflect.ValueOf(b)
        fmt.Printf("rVal kind =%v\n", rVal.Kind())
        rVal.Elem().SetInt(1)
    }
    
    type Student struct {
        Name string
        Age  int
    }
    
    func main() {
        var b int = 10
        reflectTest01(b)
        fmt.Println("-------------")
    
        stu := Student{
            Name: "tom",
            Age:  12,
        }
        reflectTest02(stu)
        fmt.Println("-------------")
        var c int = 100
        changeValue(&c)
        fmt.Println(c)
    }
    

    反射操作相关代码(结构体)

    package main
    import (
        "fmt"
        "reflect"
    )
    type Monster struct {
        Name  string `json:"name"`
        Age   int    `json:"age"`
        Score float32
        Sex   string
    }
    
    func (s Monster) Print() {
        fmt.Println("-----start-------")
        fmt.Println(s)
        fmt.Println("-----end-------")
    }
    func (s Monster) GetSum(n1, n2 int) int {
        return n1 + n2
    }
    func (s Monster) Set(name string, age int, score float32, sex string) {
        s.Name = name
        s.Age = age
        s.Score = score
        s.Sex = sex
    }
    
    func TestStruct(a interface{}) {
        rType := reflect.TypeOf(a)
        rVal := reflect.ValueOf(a)
        kd := rVal.Kind()
        if kd != reflect.Struct {
            fmt.Println("expect struct")
            return
        }
        num := rVal.NumField()
        fmt.Println("struct fields:", num)
        //变量结构体的所有字段
        for i := 0; i < num; i++ {
            fmt.Printf("field %d:值为:%v\n", i, rVal.Field(i))
            tagVal := rType.Field(i).Tag.Get("json")
            if tagVal != "" {
                fmt.Printf("field %d: tag为=%v\n", i, tagVal)
            }
        }
    
        //结构体的方法操作
        numOfMethod := rVal.NumMethod()
        fmt.Printf("struct has %d methods\n", numOfMethod)
    
        //var params []reflect.Value
        rVal.Method(1).Call(nil)
    
        //调用结构体的第1个方法Method(0)
        var params []reflect.Value
        params = append(params, reflect.ValueOf(10))
        params = append(params, reflect.ValueOf(40))
        res := rVal.Method(0).Call(params)
        fmt.Println("res = ", res[0].Int())
        //反射修改字段
    
    }
    func main() {
        var a Monster = Monster{
            Name:  "tom",
            Age:   100,
            Score: 30.1,
            Sex:   "男",
        }
        TestStruct(a)
    }
    
    
    

    相关文章

      网友评论

        本文标题:go语言反射

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