美文网首页
go语言反射reflection

go语言反射reflection

作者: 运维技术栈 | 来源:发表于2019-05-13 22:06 被阅读0次

    反射:可以在运行时动态获取变量的相关信息

    go语言中通过reflect包操作反射

    获取基本类型

    reflect.TypeOf()  //获取变量的类型,返回reflect.Type类型 
    reflect.ValueOf()  //获取变量的值,返回reflect.Value类型 
    reflect.Value.Kind()  //获取变量的类别,返回一个常量 
    reflect.Value.Interface()  //转换成interface{}类型
    

    例子:

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    func main() {
        var a float64 = 3.14
        fmt.Println("type: ", reflect.TypeOf(a))
        b := reflect.ValueOf(a)
        fmt.Println("value: ", b)
        fmt.Println("type: ", b.Type())
        fmt.Println("kind: ", b.Kind())
        fmt.Println("value: ", b.Float())
    
        fmt.Println(b.Interface())
        fmt.Printf("value is %5.2e\n", b.Interface())
        c := b.Interface().(float64)
        fmt.Println(c)
    }
    

    输出结果:

    type:  float64
    value:  3.14
    type:  float64
    kind:  float64
    value:  3.14
    3.14
    value is 3.14e+00
    3.14
    

    获取结构体

    例子:

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    type Member struct {
        Name string
        Age  int
    }
    
    func testStruct(b interface{}) {
        t := reflect.TypeOf(b)
        fmt.Println("type: ", t)
    
        v := reflect.ValueOf(b)
        fmt.Println("value: ", v)
    
        k := v.Kind()
        fmt.Println("kind: ", k)
    
        iv := v.Interface()
    
        mem, ok := iv.(Member)
        if ok {
            fmt.Printf("%v %T\n", mem, mem)
        }
    }
    
    func main() {
        var a = Member{
            Name: "Musker",
            Age:  22,
        }
        testStruct(a)
    }
    

    输出结果:

    type:  main.Member
    value:  {Musker 22}
    kind:  struct
    {Musker 22} main.Member
    

    Elem反射操作基本类型

    用来获取指针指向的变量,相当于: var a *int;

    例子

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    func testEm(a interface{}) {
        val := reflect.ValueOf(a)
        ve := val.Elem()
        ve.SetInt(100)
        b := ve.Int()
    
        fmt.Printf("get value interface{} %d\n", b)
        fmt.Printf("string val: %d\n", val.Elem().Int())
    }
    
    func main() {
        var a int = 1
        fmt.Println("before: ", a)
        testEm(&a)
        fmt.Println("after: ", a)
    }
    

    输出结果:

    before:  1
    get value interface{} 100
    string val: 100
    after:  100
    

    反射调用结构体方法

    例子:

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    type Student struct {
        Name  string
        Age   int
        Score float32
    }
    
    func (s Student) Print() {
        fmt.Println(s)
    }
    
    func (s Student) Set(name string, age int, score float32) {
        s.Name = name
        s.Age = age
        s.Score = score
    }
    
    func TestStruct(a interface{}) {
        val := reflect.ValueOf(a)
        kd := val.Kind()
    
        fmt.Println(val, kd)
        // 判断是否为struct
        if kd != reflect.Struct {
            fmt.Println("expect struct")
            return
        }
    
        // 获取字段数量
        fields := val.NumField()
        fmt.Printf("strut has %d field\n", fields)
    
        // 获取字段类型
        for i := 0; i < fields; i++ {
            fmt.Printf("%d %v\n", i, val.Field(i).Kind())
        }
    
        // 获取方法数量
        methods := val.NumMethod()
        fmt.Printf("struct has %d methods\n", methods)
    
        // 反射调用Print方法
        var params []reflect.Value
        // params为参数列表,此处为[]
        val.Method(0).Call(params)
    }
    
    func main() {
        var a Student = Student{
            Name:  "Musker",
            Age:   22,
            Score: 99.99,
        }
        TestStruct(a)
    }
    

    输出结果:

    {Musker 22 99.99} struct
    strut has 3 field
    0 string
    1 int
    2 float32
    struct has 2 methods
    {Musker 22 99.99}
    

    Elem反射操作结构体

    例子:

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    type Student struct {
        Name  string
        Age   int
        Score float32
    }
    
    func (s Student) Print() {
        fmt.Println(s)
    }
    
    func TestStruct(a interface{}) {
        val := reflect.ValueOf(a)
        kd := val.Kind()
    
        fmt.Println(val, kd)
        if kd != reflect.Ptr && val.Elem().Kind() == reflect.Struct {
            fmt.Println("expect struct")
            return
        }
    
        // 获取字段数量
        fields := val.Elem().NumField()
        fmt.Printf("struct has %d field\n", fields)
    
        //获取字段类型
        for i := 0; i < fields; i++ {
            fmt.Printf("%d %v\n", i, val.Elem().Field(i).Kind())
        }
    
        // 获取方法数量
        methods := val.Elem().NumField()
        fmt.Printf("struct has %d methods\n", methods)
    
        // 反射调用Print方法
        var params []reflect.Value
        val.Elem().Method(0).Call(params)
    
    }
    
    func main() {
        var a Student = Student{
            Name:  "stu01",
            Age:   18,
            Score: 92.8,
        }
        TestStruct(&a)
    }
    

    输出结果:

    &{stu01 18 92.8} ptr
    struct has 3 field
    0 string
    1 int
    2 float32
    struct has 3 methods
    {stu01 18 92.8}
    

    Elem反射获取tag

    例子:

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    type Student struct {
        Name  string `json:"stu_name"`
        Age   int
        Score float32
    }
    
    func TestStruct(a interface{}) {
        typ := reflect.TypeOf(a)
    
        tag := typ.Elem().Field(0).Tag.Get("json")
        fmt.Printf("tag: %s\n", tag)
    }
    
    func main() {
        var a Student = Student{
            Name:  "Musker",
            Age:   22,
            Score: 99.99,
        }
        TestStruct(&a)
    }
    

    输出结果:

    tag: stu_name
    

    相关文章

      网友评论

          本文标题:go语言反射reflection

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