9.1 Go 反射

9.1 Go 反射

反射:可以在运行时,动态获取变量的信息,比如变量的类型,类别

1.对于结构体变量,还可以获取到结构体的字段,方法

2.实现这个功能的是 reflect包

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

使用反射场景,json序列化

package main

import (
    "encoding/json"
    "fmt"
)

type Student struct {
    Name  string `json:"学生名"`
    Age   int    `json:"学生年纪"`
    Class string `json:"班级"`
}

func main() {
    stu := Student{
        "尼古拉斯赵四",
        18,
        "舞王班",
    }
    data, err := json.Marshal(stu)
    if err != nil {
        fmt.Println("序列化出错", err)
    }
    fmt.Println("json序列化结果:", string(data))
}

反射获取基本类型

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var num int64 = 12345
    fmt.Println("num类型", reflect.TypeOf(num))
    //获取变量的值
    resNum := reflect.ValueOf(num)
    fmt.Printf("类型:%T  值:%v\n", resNum, resNum)
    fmt.Printf("resNum值:%v\n", resNum)
    fmt.Printf("resNum类型:%v\n", resNum.Type())
    fmt.Printf("resNum种类:%v\n", resNum.Kind())
    fmt.Printf("resNum确认值:%v\n", resNum.Int())
}

反射获取结构体

package main

import (
    "fmt"
    "reflect"
)

//学生结构体
type Student struct {
    Name  string
    Age   int
    Score float32
}

//函数接收类型是接口,可以接收任何类型
func test(b interface{}) {
    t := reflect.TypeOf(b)
    fmt.Println("参数类型:", t)

    v := reflect.ValueOf(b)
    fmt.Println("参数值:", v)

    k := v.Kind()
    fmt.Println("参数种类:", k)
    //转化为接口返回
    iv := v.Interface()
    fmt.Printf("类型:%T 值:%v\n", iv, iv)
    //类型断言,如果这个接口是student类型
    stu, ok := iv.(Student)
    if ok {
        fmt.Printf("结构体值:%v 类型:%T\n", stu, stu)
    }
}

func main() {
    var a Student = Student{
        Name:  "周星驰",
        Age:   18,
        Score: 99,
    }
    //传入结构体
    test(a)
}

反射elem获取指针指向的变量

package main

import (
    "fmt"
    "reflect"
)

//fv.Elem()用来获取指针指向的变量
func testInt(b interface{}) {
    //获取b的类型
    val := reflect.ValueOf(b)
    fmt.Printf("参数b的类型是:%T 值是:%v\n", val, val)
    fmt.Printf("val.Elem()获取到变量的类型:%T 值:%v\n", val.Elem(), val.Elem())
    //修改val的值
    val.Elem().SetInt(100)
    //返回 一个int值类型
    c := val.Elem().Int()
    fmt.Printf("类型:%T 值是:%d\n", c, c)
}

func main() {
    var b int = 1
    b = 200
    testInt(&b)
    fmt.Println("b的值:", b)
}

理解reflect.Value.Elem()

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var num int = 100
    //返回变量的值,传入地址,那就是内存地址的值
    fn := reflect.ValueOf(&num)
    //修改指针指向的值,也就是修改num的值
    fn.Elem().SetInt(222)
    fmt.Printf("此时num的值:%d\n", num)

    //以上操作,等同于
    var num2 = 111
    var b *int = &num2
    *b = 333
    fmt.Printf("b的类型:%T\n", b)
    fmt.Println(num2)
}
上一篇:Proxy + Reflect 实现 响应的数据变化


下一篇:go语言判断 slice,array,map中是否存在某个元素