美文网首页工作生活
14.手撕Go语言-反射

14.手撕Go语言-反射

作者: imsilence | 来源:发表于2019-06-30 19:03 被阅读0次

    反射是指在运行时动态的访问和修改任意类型对象的结构和成员,在go语言中提供reflect包提供反射的功能,每一个变量都有两个属性:类型(Type)和值(Value)

    Type

    reflect.Type是一个接口类型,用于获取变量类型的信息,可通过reflect.TypeOf函数获取某个变量的类型信息

    通用方法

    • Name(): 类型名

    • PkgPath(): 包路径

    • Kind(): 类型枚举值

    • String(): Type字符串

    • Comparable(): 是否可进行比较

    • Implements(Type): 是否实现某接口

    • AssignableTo(Type): 是否可赋值给某类型

    • ConvertibleTo(Type): 是否可转换为某类型

    • NumMethod(): 方法个数

    • Method(int): 通过索引获取方法类型

      Method结构体常用属性:

      • Name:方法名
      • Type:函数类型
      • Func:方法值(Value)
    • MethodByName(string): 通过方法名字获取方法类型

    特定类型方法

    1. reflect.Int, reflect.UInt,reflect.Float,reflect.Complex

      • Bits(): 获取占用字节位数
    2. reflact.Array

      • Len(): 获取数组长度
      • Elem(): 获取数据元素类型
    3. reflect.Slice

      • Elem(): 获取切片元素类型
    4. reflect.Map

      • Key(): 获取映射键类型
      • Elem(): 获取映射值类型
    5. reflect.Ptr

      • Elem(): 获取指向值类型
    6. reflect.Func

      • IsVariadic(): 是否具有可变参数
      • NumIn(): 参数个数
      • In(int): 通过索引获取参数类型
      • NumOut(): 返回值个数
      • Out(int): 通过索引获取返回值类型
    7. reflect.Struct

      • NumField(): 属性个数

      • Field(int):通过索引获取属性

        StructField结构体常用属性:

        • Name:属性名

        • Anonymous:是否为匿名

        • Tag:标签

          StructTag常用方法:

          • Get(string)
          • Lookup(string)
      • FieldByName(string): 通过属性名获取属性

    Value

    reflect.Value是一个结构体类型,用于获取变量值的信息,可通过reflect.ValueOf函数获取某个变量的值信息

    通用方法

    • Type(): 获取值类型
    • CanAddr():是否可获取地址
    • Addr(): 获取地址
    • CanInterface(): 是否可以获取接口的
    • InterfaceData():
    • Interface(): 将变量转换为interface{}
    • CanSet(): 是否可更新
    • isValid(): 是否初始化为零值
    • Kind():获取值类型枚举值
    • NumMethod(): 方法个数
    • Method(int): 通过索引获取方法值
    • MethodByName(string): 通过方法名字获取方法值
    • Convert(Type):转换为对应类型的值

    修改方法

    • Set/Set*:设置变量值

    调用方法

    • Call
    • CallSlice

    特定类型方法

    1. reflect.Int, reflect.Uint,

      • Int(): 获取对应类型值
      • Unit():获取对应类型值
    2. reflect.Float*

      • Float():获取对应类型值
    3. reflect.Complex*

      • Complex():获取对应类型值
    4. reflact.Array

      • Len(): 获取数组长度
      • Index(int): 根据索引获取元素
      • Slice(int, int): 获取切片
      • Slice3(int, int, int): 获取切片
    5. reflect.Slice

      • IsNil(): 判断是否为
      • Len(): 获取元素数量
      • Cap(): 获取容量
      • Index(int): 根据索引获取元素
      • Slice(int, int): 获取切片
      • Slice3(int, int, int): 获取切片
    6. reflect.Map

      • IsNil(): 判断是否为
      • Len(): 获取元素数量
      • MapKeys(): 获取所有键
      • MapIndex(Value): 根据键获取值
      • MapRange():获取键值组成的可迭代对象
    7. reflect.Ptr

      • Elem(): 获取指向值类型(解引用)
    8. reflect.Func

      • IsVariadic(): 是否具有可变参数
      • NumIn(): 参数个数
      • In(int): 通过索引获取参数类型
      • NumOut: 返回值个数
      • Out(int): 通过索引获取返回值类型
    9. reflect.Struct

      • NumField(): 属性个数

      • Field(int):通过索引获取属性

        StructField结构体常用属性:

        • Name:属性名

        • Anonymous:是否为匿名

        • Tag:标签

          StructTag常用方法:

          • Get(string)
          • Lookup(string)
        • FieldByName(string): 通过属性名获取属性

    开发

    objs包中创建用于测试的对象

    14.01.png 14.02.png

    打印变量类型信息

    14.03.png 14.04.png 14.05.png 14.06.png 14.07.png 14.08.png

    打印变量值信息

    14.09.png 14.10.png 14.11.png 14.12.png

    对于包中的未公开属性可以通过反射获取到

    更新变量值

    14.13.png 14.14.png 14.15.png

    变量可修改的条件:

    1. 对于基本数据类型变量可获取地址
    2. 对于结构体属性必须是可获取地址且为公开的属性

    调用函数

    14.16.png 14.17.png 14.18.png

    动态创建结构体

    14.19.png

    动态创建函数并调用

    14.20.png 14.21.png

    应用

    反射常用在动态处理所有数据类型(json/xml序列化和反序列化, orm等)或调用所有函数(路由函数调用)的场景

    encoding/json

    1. 介绍

      在内存数据进行持久化存储或网络交换时常可采用json格式字符串,go语言提供json包进行json序列化和反序列化

      对于Go提供的基本类型和符合类型可以直接使用json包进行序列化和反序列化操作,针对结构体可通过标签声明属性和json字符串的转换关系,标签名为json,常用格式为:

      • json:

        默认形式,可省略,json键名使用属性名,类型通过属性对应的类型

      • json:"key"

        json键名使用指定名称key

      • json:"-"

        忽略该属性

      • json:"key,type"

        json键名使用指定名称key,类型使用指定类型type

      • json:"key,omitempty"

        json键名使用指定名称key,当值为零值时省略该属性

      • json:"key,type,omitempty"

        json键名使用指定名称key,类型使用指定类型type,当值为零值时省略该属性

      • json:",type"

        类型使用指定类型type

      • json:",omitempty"

        值为零值时省略该属性

      14.22.png
    2. 数据初始化

      14.23.png 14.24.png
    3. 常用函数

      • Marshal: 用于将go语言的数据序列化为json字符串

      • Indent: 将json字符串进行格式化

        14.25.png
      • UnMarshal: 用于json字符串反序列化为go语言的数据

        14.26.png
      • MarshalIndent: 用于将go语言的数据序列化为格式化的json字符串

        14.27.png
      • Valid: 验证是否为正确json字符串

        14.28.png
    4. Encoder与Decoder

      Encoder与Decoder是构建在流之上进行JSON序列化与反序列化,构造函数分别为NewEncoder和NewDecoder,参数要求分别实现接口io.Writer和io.Reader的对象

      • Encoder.Encode序列化

        14.29.png
      • Decoder.Decode反序列化

        14.30.png

    encoding/xml

    1. 介绍

      go语言提供xml包进行xml序列化和反序列化

      在进行xml序列化和反序列化时,必须定义根结构体对应xml的根节点,并可通过结构体中xml.Name类型且名称为XMLName属性来定义根节点,可通过各属性的标签声明属性和xml节点的转换关系,标签名为xml,常用格式为:

      • xml:

        默认形式,可省略,xml节点使用结构体属性名

      • xml:"name"

        xml节点名使用指定的名称name

      • xml:"-"

        忽略该属性

      • xml:"name,attr"

        表示该属性为节点的属性值,属性名使用指定名称name

      • xml:",attr"

        表示为节点的属性值,属性名为结构体属性名

      • xml:"name,omitempty"

        xml节点名使用指定的名称name,当值为零值时省略该属性

      • xml:",omitempty"

        值为零值时省略该属性

      • xml:", chardata"

        表示为文本

      • xml:",cdata"

        表示使用CDATA包含

      • xml:",comment"

        表示为注释内容

      • xml:", innerxml"

        表示为数据不进行实体编码

      • xml:"A>B>C"

        定义XML节点结构

      14.31.png
    2. 数据初始化

      14.32.png 14.33.png
    3. 常用函数

      • Marshal: 用于将go语言的数据序列化为xml字符串

        14.34.png
      • UnMarshal: 用于xml字符串反序列化为go语言的数据

        14.35.png
      • MarshalIndent: 用于将go语言的数据序列化为格式化的xml字符串

        14.36.png

    相关文章

      网友评论

        本文标题:14.手撕Go语言-反射

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