• go语言 | 图解反射(一)


    反射

    反射是指在程序运行期对程序本身进行访问和修改的能力

    变量的内在机制

    变量包含类型信息和值信息 var arr [10]int arr[0] = 10
    类型信息:是静态的元信息,是预先定义好的
    值信息:是程序运行过程中动态改变的

    反射的使用

    reflect包封装了反射相关的方法
    获取类型信息:reflect.TypeOf,是静态的
    获取值信息:reflect.ValueOf,是动态的

    示例1

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    type User struct {
    	Name string
    	Age  int
    }
    
    func main() {
    	u := User{"tom", 27}
    
    	// 获取类型的具体信息
    	t := reflect.TypeOf(u)
    	fmt.Println(t.Name()) // User
    	fmt.Println(t.Kind()) // struct
    	v := reflect.ValueOf(u)
    	fmt.Println(v)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    输出:

    User
    struct
    {tom 27}
    
    • 1
    • 2
    • 3

    示例2

    反射可以在运行时动态获取程序的各种详细信息
    反射获取interface类型信息

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    //反射获取interface类型信息
    
    func reflect_type(a interface{}) {
    	t := reflect.TypeOf(a)
    	fmt.Println("类型是:", t)
    	// kind()可以获取具体类型
    	k := t.Kind()
    	fmt.Println(k)
    	switch k {
    	case reflect.Float64:
    		fmt.Printf("a is float64\n")
    	case reflect.String:
    		fmt.Println("string")
    	}
    }
    
    func main() {
    	var x float64 = 3.4
    	reflect_type(x)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    输出

    类型是: float64
    float64
    a is float64
    
    • 1
    • 2
    • 3

    示例3

    反射获取interface值信息

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    //反射获取interface值信息
    
    func reflect_value(a interface{}) {
    	v := reflect.ValueOf(a)
    	fmt.Println(v)
    	k := v.Kind()
    	fmt.Println(k)
    	switch k {
    	case reflect.Float64:
    		fmt.Println("a是:", v.Float())
    	}
    }
    
    func main() {
    	var x float64 = 3.4
    	reflect_value(x)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    输出

    3.4
    float64
    a是: 3.4
    
    
    • 1
    • 2
    • 3
    • 4

    示例4

    反射修改值信息

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    // 反射修改值
    func reflect_set_value(a interface{}) {
    	v := reflect.ValueOf(a)
    	k := v.Kind()
    	switch k {
    	case reflect.Float64:
    		// 反射修改值
    		v.SetFloat(6.9)
    		fmt.Println("a is ", v.Float())
    	case reflect.Ptr:
    		// Elem()获取地址指向的值
    		v.Elem().SetFloat(7.9)
    		fmt.Println("case:", v.Elem().Float())
    		// 地址
    		fmt.Println(v.Pointer())
    	}
    }
    
    func main() {
    	var x float64 = 3.4
    	fmt.Println("main:", x)
    	// 反射认为下面是指针类型,不是float类型
    	reflect_set_value(&x)
    	fmt.Println("main:", x)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    输出

    main: 3.4
    case: 7.9
    1374390181912
    main: 7.9
    
    • 1
    • 2
    • 3
    • 4

    示例5

    查看类型、字段和方法

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    // 定义结构体
    type User struct {
    	Id   int
    	Name string
    	Age  int
    }
    
    // 绑方法
    func (u User) Hello() {
    	fmt.Println("Hello")
    }
    
    // 传入interface{}
    func Poni(o interface{}) {
    	t := reflect.TypeOf(o)
    	fmt.Println("类型:", t)
    	fmt.Println("字符串类型:", t.Name())
    	// 获取值
    	v := reflect.ValueOf(o)
    	fmt.Println(v)
    	// 可以获取所有属性
    	// 获取结构体字段个数:t.NumField()
    	for i := 0; i < t.NumField(); i++ {
    		// 取每个字段
    		f := t.Field(i)
    		fmt.Printf("%s : %v", f.Name, f.Type)
    		// 获取字段的值信息
    		// Interface():获取字段对应的值
    		val := v.Field(i).Interface()
    		fmt.Println("val :", val)
    	}
    	fmt.Println("=================方法====================")
    	for i := 0; i < t.NumMethod(); i++ {
    		m := t.Method(i)
    		fmt.Println(m.Name)
    		fmt.Println(m.Type)
    	}
    
    }
    
    func main() {
    	u := User{1, "zs", 20}
    	Poni(u)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    输出

    类型: main.User
    字符串类型: User
    {1 zs 20}
    Id : intval : 1
    Name : stringval : zs
    Age : intval : 20
    =================方法====================
    Hello
    func(main.User)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    示例6

    查看匿名字段

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    // 定义结构体
    type User struct {
        Id   int
        Name string
        Age  int
    }
    
    // 匿名字段
    type Boy struct {
        User
        Addr string
    }
    
    func main() {
        m := Boy{User{1, "zs", 20}, "bj"}
        t := reflect.TypeOf(m)
        fmt.Println(t)
        // Anonymous:匿名
        fmt.Printf("%#v\n", t.Field(0))
        // 值信息
        fmt.Printf("%#v\n", reflect.ValueOf(m).Field(0))
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    输出

    main.Boy
    reflect.StructField{Name:"User", PkgPath:"", Type:(*reflect.rtype)(0x102b8b100), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:true}
    main.User{Id:1, Name:"zs", Age:20}
    
    • 1
    • 2
    • 3

    示例7

    修改结构体的值

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    // 定义结构体
    type User struct {
        Id   int
        Name string
        Age  int
    }
    
    // 修改结构体值
    func SetValue(o interface{}) {
        v := reflect.ValueOf(o)
        // 获取指针指向的元素
        v = v.Elem()
        // 取字段
        f := v.FieldByName("Name")
        if f.Kind() == reflect.String {
            f.SetString("kuteng")
        }
    }
    
    func main() {
        u := User{1, "5lmh.com", 20}
        SetValue(&u)
        fmt.Println(u)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    输出

    {1 kuteng 20}
    
    • 1

    示例8

    调用方法

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    // 定义结构体
    type User struct {
    	Id   int
    	Name string
    	Age  int
    }
    
    func (u User) Hello(name string) {
    	fmt.Println("Hello:", name)
    }
    
    func main() {
    	u := User{1, "5lmh.com", 20}
    	v := reflect.ValueOf(u)
    	// 获取方法
    	m := v.MethodByName("Hello")
    	// 构建一些参数
    	args := []reflect.Value{reflect.ValueOf("6666")}
    	// 没参数的情况下:var args2 []reflect.Value
    	// 调用方法,需要传入方法的参数
    	m.Call(args)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    输出

    Hello: 6666
    
    • 1

    示例9

    获取字段的tag

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    type Student struct {
        Name string `json:"name1" db:"name2"`
    }
    
    func main() {
        var s Student
        v := reflect.ValueOf(&s)
        // 类型
        t := v.Type()
        // 获取字段
        f := t.Elem().Field(0)
        fmt.Println(f.Tag.Get("json"))
        fmt.Println(f.Tag.Get("db"))
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    输出

    name1
    name2
    
    • 1
    • 2

    参考

    https://www.topgoer.com/%E5%B8%B8%E7%94%A8%E6%A0%87%E5%87%86%E5%BA%93/%E5%8F%8D%E5%B0%84.html

  • 相关阅读:
    基于神经网络的柯氏音血压计
    2、SySeVR环境配置(下)
    day52|300.最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组
    【十问十答】回归模型知识点
    MySQL CREATE TABLE 简单设计模板交流
    极客日报:抖音否认进入外卖行业;谷歌发布Android 12硬件门槛;IntelliJ IDEA 2021.3 EAP 4发布
    武汉新时标文化传媒有限公司“土味”正在崛起,短视频的春天来了
    学习 MySQL:什么是分页
    AWS IAM介绍
    kafka系列七、kafka核心配置(转)
  • 原文地址:https://blog.csdn.net/qq_40318498/article/details/134318074