广告位联系
返回顶部
分享到

Go语言开发框架反射机制及常见函数示例介绍

Golang 来源:互联网 作者:佚名 发布时间:2022-09-26 20:49:26 人浏览
摘要

基本介绍 反射可以在运行时动态获取变量的各种信息,比如变量的类型,类别 如果是结构体变量,还可以获取到结构体本身的信息 通过反射,可以修改变量的值,可以调用关联的方法 使用反

基本介绍

  • 反射可以在运行时动态获取变量的各种信息,比如变量的类型,类别
  • 如果是结构体变量,还可以获取到结构体本身的信息
  • 通过反射,可以修改变量的值,可以调用关联的方法
  • 使用反射,需要import("reflect")

示意图

反射中常见函数和概念

reflect.TypeOf(变量名)

获取变量的类型,返回reflect.Type类型

reflect.ValueOf(变量名)

获取变量的值,返回reflect.Value类型reflect.Value是一个结构体类型,通过reflect.Value,可以获取到关于该变量的很多信息

变量.interface{}和reflect.Value是可以相互转换的

基本使用

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

package main

import (

   "fmt"

   "reflect"

)

/*

1.编写案例,对基本数据类型,interface{},reflect.Value进行反射

2.编写案例,对结构体,interface{},reflect.Value进行反射

*/

func reflectTest(b interface{}){

   //打印出传参的type,kind,value

   fmt.Printf("b的类型为%v,b的kind为%v,value为%v\n",reflect.TypeOf(b),reflect.ValueOf(b).Kind(),reflect.ValueOf(b))    //b的类型为int,b的kind为int,value为100

   //reflect.TypeOf(),reflect.ValueOf()返回的类型

   fmt.Printf("reflect.TypeOf()返回类型为%T,reflect.ValueOf()返回类型为%T\n",reflect.TypeOf(b),reflect.ValueOf(b)) //reflect.TypeOf()返回类型为*reflect.rtype,reflect.ValueOf()返回类型为reflect.Value

}

type Student struct {

   Name string

   age int

}

func reflectTest2(b interface{}){

   rTyp:=reflect.TypeOf(b)

   fmt.Println(rTyp) //main.Student

   rVal:=reflect.ValueOf(b)

   //将rVal转换成interface{}

   iV:=rVal.Interface()

   fmt.Printf("iv=%v type=%T\n",iV,iV) //iv={张三 18} type=main.Student

   //因为Go语言是静态语言,所以不能直接获取结构体中指定的值,所以我需要将其断言成需要的类型

   stu,ok:=iV.(Student)

   if ok{

    fmt.Printf(stu.Name,stu.age)  //张三%!(EXTRA int=18)

   }

}

func main() {

   //1.编写案例,对基本数据类型,interface{},reflect.Value进行反射

   var num int =100

   reflectTest(num)

   //2.编写案例,对结构体,interface{},reflect.Value进行反射

   stu:=Student{

    Name: "张三",

    age:  18,

   }

   reflectTest2(stu)

}

反射注意事项

  • reflect.ValueKind,获取的变量的类别,返回的是一个常量
  • Type是类型,Kind是类别,Type和Kind可能是相同的,也可能是不同的,例如结构体
  • 通过反射可以在让变量在interface{}和reflect.Value之间相互转换
  • 通过反射的方式获取变量的值(并返回对应的类型),要求数据类型匹配,比如x是int,那么就应该使用reflect.Value(x).Int(),而不能使用其他的,否则报panic
  • 通过反射来修改变量,注意当使用Setxxx方法来设置需要通过对应的指针类型来完成,这样才能改变传入变量的值,同时需要使用到reflect.Value.Elem()方法

反射的最佳实践

使用反射来遍历结构体的字段,调用结构体的方法,并获取结构体标签的值

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

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

package main

import (

    "fmt"

    "reflect"

)

//定义了一个Monster结构体

type Monster struct {

    Name  string `json:"name"`

    Age   int `json:"monster_age"`

    Score float32 `json:"成绩"`

    Sex   string

}

//方法,返回两个数的和

func (s Monster) GetSum(n1, n2 int) int {

    return n1 + n2

}

//方法, 接收四个值,给s赋值

func (s Monster) Set(name string, age int, score float32, sex string) {

    s.Name = name

    s.Age = age

    s.Score = score

    s.Sex = sex

}

//方法,显示s的值

func (s Monster) Print() {

    fmt.Println("---start~----")

    fmt.Println(s)

    fmt.Println("---end~----")

}

func TestStruct(a interface{}) {

    //获取reflect.Type 类型

    typ := reflect.TypeOf(a)

    //获取reflect.Value 类型

    val := reflect.ValueOf(a)

    //获取到a对应的类别

    kd := val.Kind()

    //如果传入的不是struct,就退出

    if kd !=  reflect.Struct {

        fmt.Println("expect struct")

        return

    }

    //获取到该结构体有几个字段

    num := val.NumField()

    fmt.Printf("struct has %d fields\n", num) //4

    //变量结构体的所有字段

    for i := 0; i < num; i++ {

        fmt.Printf("Field %d: 值为=%v\n", i, val.Field(i))

        //获取到struct标签, 注意需要通过reflect.Type来获取tag标签的值

        tagVal := typ.Field(i).Tag.Get("json")

        //如果该字段于tag标签就显示,否则就不显示

        if tagVal != "" {

            fmt.Printf("Field %d: tag为=%v\n", i, tagVal)

        }

    }

    //获取到该结构体有多少个方法

    numOfMethod := val.NumMethod()

    fmt.Printf("struct has %d methods\n", numOfMethod)

    //var params []reflect.Value

    //方法的排序默认是按照 函数名的排序(ASCII码)

    val.Method(1).Call(nil) //获取到第二个方法。调用它

    //调用结构体的第1个方法Method(0)

    var params []reflect.Value  //声明了 []reflect.Value

    params = append(params, reflect.ValueOf(10))

    params = append(params, reflect.ValueOf(40))

    res := val.Method(0).Call(params) //传入的参数是 []reflect.Value, 返回[]reflect.Value

    fmt.Println("res=", res[0].Int()) //返回结果, 返回的结果是 []reflect.Value*/

}

func main() {

    //创建了一个Monster实例

    var a Monster = Monster{

        Name:  "黄鼠狼精",

        Age:   400,

        Score: 30.8,

    }

    //将Monster实例传递给TestStruct函数

    TestStruct(a)  

}


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://juejin.cn/post/7146400351103483940
相关文章
  • 基于GORM实现CreateOrUpdate的方法
    CreateOrUpdate 是业务开发中很常见的场景,我们支持用户对某个业务实体进行创建/配置。希望实现的 repository 接口要达到以下两个要求: 如果
  • Golang中的内存逃逸的介绍
    什么是内存逃逸分析 内存逃逸分析是go的编译器在编译期间,根据变量的类型和作用域,确定变量是堆上还是栈上 简单说就是编译器在编译
  • Golang自旋锁的介绍
    自旋锁 获取锁的线程一直处于活跃状态,但是并没有执行任何有效的任务,使用这种锁会造成busy-waiting。 它是为实现保护共享资源而提出的
  • Go语言读写锁RWMutex的源码

    Go语言读写锁RWMutex的源码
    在前面两篇文章中初见 Go Mutex、Go Mutex 源码详解,我们学习了Go语言中的Mutex,它是一把互斥锁,每次只允许一个goroutine进入临界区,可以保
  • Go项目实现优雅关机与平滑重启功能
    什么是优雅关机? 优雅关机就是服务端关机命令发出后不是立即关机,而是等待当前还在处理的请求全部处理完毕后再退出程序,是一种对
  • Go语言操作Excel利器之excelize类库的介绍
    在开发中一些需求需要通过程序操作excel文档,例如导出excel、导入excel、向excel文档中插入图片、表格和图表等信息,使用Excelize就可以方便
  • 利用Go语言快速实现一个极简任务调度系统

    利用Go语言快速实现一个极简任务调度系统
    任务调度(Task Scheduling)是很多软件系统中的重要组成部分,字面上的意思是按照一定要求分配运行一些通常时间较长的脚本或程序。在爬
  • GoLang中的iface 和 eface 的区别介绍

    GoLang中的iface 和 eface 的区别介绍
    GoLang之iface 和 eface 的区别是什么? iface和eface都是 Go 中描述接口的底层结构体,区别在于iface描述的接口包含方法,而eface则是不包含任何方
  • Golang接口使用的教程
    go语言并没有面向对象的相关概念,go语言提到的接口和java、c++等语言提到的接口不同,它不会显示的说明实现了接口,没有继承、子类、
  • go colly 爬虫实现示例介绍
    贡献某CC,go源码爬虫一个,基于colly,效果是根据输入的浏览器cookie及excel必要行列号,从excel中读取公司名称,查询公司法人及电话号码。
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计