Golang学习之---反射机制(九)

  1. func TypeOf(i interface{}) Type:获取reflect.Type 类型
    TypeOf返回接口中保存的值的类型,TypeOf(nil)会返回nil。
  2. func ValueOf(i interface{}) Value:获取reflect.Value 类型
    ValueOf返回一个初始化为i接口保管的具体值的Value,ValueOf(nil)返回Value零值。
  3. 获取变量对应的类别kind,有两种方式:
    (1)Type接口中的方法 Kind() Kind:Kind返回该接口的具体分类
    (2)func (v Value) Kind() Kind:Kind返回v持有的值的分类,如果v是Value零值,返回值为Invalid
  4. func (v Value) String() string:返回字符串形式
    返回v持有的值的字符串表示。因为go的String方法的惯例,Value的String方法比较特别。和其他获取v持有值的方法不同:v的Kind是String时,返回该字符串;v的Kind不是String时也不会panic而是返回格式为"<T value>"的字符串,其中T是v持有值的类型。
  5. func (v Value) Interface() (i interface{})
    本方法返回v当前持有的值(表示为/保管在interface{}类型),等价于:新定义了一个空接口类型,并将v赋给空接口类型
  6. func (v Value) Elem() Valuev必须是指针类型或空接口类型,取得v指向的值
    Elem返回v持有的接口保管的值的Value封装,或者v持有的指针指向的值的Value封装。如果v的Kind不是Interface或Ptr会panic;如果v持有的值为nil,会返回Value零值。



    =================结构体字段field============
  7. func (v Value) NumField() int:获取该结构体有几个字段,这里的Value是reflect.Value类型
    返回v持有的结构体类型值的字段数,如果v的Kind不是Struct会panic
  8. func (v Value) Field(i int) Value:返回结构体的第i个字段的值
    返回结构体的第i个字段值(的Value封装)。如果v的Kind不是Struct或i出界会panic
  9. Field(i int) StructField
    返回struct类型的第i个字段的类型,如非结构体或者i不在[0, NumField())内将会panic
    常用:
    rTyp.Field(i).Tag.Get("json") :返回序列化的字段名。
    序列化json的名字是可以自定义的,但是反序列化写死了就是json。所以我们统一使用json了

  10. func (v Value) FieldByName(name string) Value:获得该字段的属性值。与.SetString连用,可以设置该字段的属性值。
    返回该类型名为name的字段(的Value封装)(会查找匿名字段及其子字段),如果v的Kind不是Struct会panic;如果未找到会返回Value零值。


    =================结构体方法method============

  11. func (v Value) NumMethod() int:获取该结构体有多少个方法
    返回v持有值的方法集的方法数目。

  12. func (v Value) Method(i int) Value:找到和reflect.Value类型绑定的第i个方法
    返回v持有值类型的第i个方法的已绑定(到v的持有值的)状态的函数形式的Value封装。
    方法的排序跟方法写的位置没有关系,而是按照ASCII码排序的。从表面看就是首字母顺序

  13. func (v Value) Call(in []Value) []Value:调用方法
    Call方法使用输入的参数in调用v持有的函数。

  14. func (v Value) Int() int64
    返回v持有的有符号整数(表示为int64),如果v的Kind不是Int、Int8、Int16、Int32、Int64会panic

一、反射

  1. 如果想要自己写一套框架,反射必用无疑。
  2. 如我们常见的:在web页面输入用户名密码后点击提交,就能跳转到对应页面。中间过程需要进入.do等类里面处理,xml的映射等都是反射在底层操作的。
  3. 包括创建一个结构体或者直接给结构体字段赋值,反射都可以完成。
  4. 通常是创建一个实例,然后调用。但是是个怎样的调用过程的呢?反射是一个有规范的。比如testing框架,必须以TestXxx打头,否则就调不起来了,中间可能是扫描目录下所有_test.go文件中的TestXxx方法。
  5. 反射里面有大量的函数,反射是在函数的应用上扩展的。
  6. reflect.Type和reflect.Value是核心。
    其中,Type是一个接口,里面有各种各样的方法;用的最多的是Value,Value是一个结构体。
  7. Kind范围大于Type。如果Kind比作电器,Type就是冰箱。Type是类型,Kind是类别。
    对基本数据类型来说,二者是一样的;对于结构体等是不一样的。
    如:结构体:Type是 “包名.Student(如: main.Student)” ,Kind是struct
  8. pkg1.Student和pkg2.Student可以同时存在,因为Go以包名区分

1.1  一个问题引出反射的使用场景

1.2 基本介绍

  1. 反射可以在运行时动态的获取变量的各种信息,比如变量的类型(type),类别(kind)
  2. 如果是结构体变量,还可以获取到结构体本身的信息(包括结构体的字段、方法)
  3. 通过反射,可以修改变量的值,可以调用关联的方法
  4. 使用反射,需要 import "reflect"
  5. 示意图:

1.3 反射重要的函数和概念

  • 3)reflect.Value.Kind 获取变量的类别,返回的是一个常量
  • 4)获取Kind有两种方式,分别是通过reflect.Type和reflect.Value。参考方法详细介绍里的代码
  • 5)Type和Kind的区别
    Kind范围大于Type。如果Kind比作电器,Type就是冰箱
    Type是类型,Kind是类别。Type和Kind可能是相同的,也可能是不同的。
    比如:var num int =10    -- num的Type是int,Kind也是int
    比如:var stu Student    -- stu的Type是包名.Student(如: main.Student),Kind是struct
  • 6)变量、interface{}和reflect.Value是可以相互转化的。这点在实际开发中,会经常使用到。示意图:


    代码:
  • 为什么要用到类型断言呢?因为反射是在运行时才知道其数据类型的,编译时没法知道。所以需要类型断言,来保证编译时不报错。断言的最佳实践见下:
  • 7)使用反射的方式来获取变量的值,并返回对应的类型,数据类型必须匹配。如:num是int类型,那么就应该使用reflect.ValueOf(num).Int(),否则报错panic
  • 8)通过反射来修改变量,注意要使用SetXxx方法通过传入对应数据类型的指针类型来设置。这样才能改变传入变量的值。同时需要reflect.ValueOf(&num).Elem()方法

  • 9)reflect.ValueOf(&num).Elem()方法怎么理解?
  • 10) 序列化的标签如何获取?rTyp.Field(i).Tag.Get("json") :返回序列化的字段名。
    序列化的时候,json字段是可以自己定义的。但是反序列化写死了就叫json

1.4 使用场景

1.5 快速入门-演示对(基本数据类型、interface{}、reflect.Value)进行反射的基本操作


1.6 快速入门-演示对(结构体类型、interface{}、reflect.Value)进行反射的基本操作


1.7 应用实例一

1、使用反射来遍历结构体的字段的值,调用结构体的方法
2、使用反射的方式获取结构体tag标签,修改字段值(都是通过地址传递的方式完成)

1.8 应用实例二 -- 桥连接

1.9 应用实例三 -- 使用反射操作任意结构体类型

1.10 应用实例四 -- 在底层直接创建结构体并赋值

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值