Go REFLECT Library反射类型详解

目录
  • 一、反射概述
  • 二、反射类型对象
    • 基本数类型的 反射类型对象
    • 引用数据类型的 反射类型对象
    • 结构体的 反射类型对象
    • 指针的 反射类型对象

一、反射概述

反射是指程序在运行期间对程序本身进行访问和修改的能力。程序在编译过程中变量会被转换为内存地址,变量名不会被编译器写入到可执行部分。在程序运行时程序无法获取自身的信息。

在静态语言中如 Java 可以在程序编译期将变量的反射信息,如字段名称、类型等信息整合到可执行文件中,并给程序提供接口访问反射信息,这样就可以在程序运行期获取类型的反射信息,并修改该它们。

对于动态语言来说如 Ruby 的动态特性相比静态语言来说可以非常简单的在程序运行时访问变量、方法或者对象信息,也可以修改它们,甚至可以动态性可以让程序自己构造并执行代码,这就是元编程。

Ruby 中的基类(Object)包含了方法 methods、常量 constants 和实例变量instance_variable 的动态获取。

puts String.method_defined?(:upcase) # 判断是否定义了 upcase 方法
puts String.methods # 获取所有方法
puts Math.const_get("PI") # 获取常量
puts Math.const_set("PII", 1000) # 设置常量
puts Math.const_defined?(:P) # 判断是否包含指定常量
puts Math.constants # 获取所有常量

因此 Ruby 这里动态解释型语言是反射系统的,但是 Go 作为一门静态编译型语言提供了 relect 标准库访问程序的反射信息。

Go 语言的反射系统无法获取到一个可执行文件空间中或者是一个包中所有类型信息,需要配合使用标准库中对应的词法和语法解析器和抽象语法书对源码进行扫描后获取这些信息

二、反射类型对象

基本数类型的 反射类型对象

在 Go 中使用 reflect 标准库下的 typeOf 函数可以获取任意变量的反射类型对象,程序通过 反射类型对象 可以访问任意变量的类型信息。

func main(){
   zulu := "stark"
   zuluType := reflect.TypeOf(zulu)
   fmt.Printf("zuluType 的类型为:%v,类型名为:%v,种类为:%v\n", zuluType, zuluType.Name(), zuluType.Kind())
}

执行上述代码,输出结果如下:

zuluType 的类型为:string,类型名为:string,种类为:string

TypeOf 函数返回一个 Type 接口,该接口包含非常多的方法

上述代码中的类型就是变量的数据类型,如基本数据类型中的 int、int64、float64、string、map、bool 以及 type 结构体类型等,类型名就是类型本身。

种类既 Kind 方法获取的信息是指对象归属的品种,在 reflect 库中对对象归属的 Kind 做了定义

Kind 的范围在如下列出的常量中

并在通过 String() 方法做了小写的转换,最终返回 Kind 为 string

Name 和 Kind 可以表示一个变量的 反射类型对象 的信息。每种数据类型变量的 反射类型对象 的 Name 和 Kind 都是不同的。

引用数据类型的 反射类型对象

func main(){
   zulu := map[string]string{
      "name": "Stark",
      "address": "NYC",
   }
   zuluType := reflect.TypeOf(zulu)
   fmt.Printf("zuluType 的类型为:%v,类型名为:%v,种类为:%v\n", zuluType, zuluType.Name(), zuluType.Kind())
}

执行上述代码,输出结果如下:

zuluType 的类型为:map[string]string,类型名为:,种类为:map

Map、Array、Slice 和 Pointer 类型的 Name() 都为空字符串

结构体的 反射类型对象

func main(){
   zulu := Zulu{"stark", 33}
   zuluType := reflect.TypeOf(zulu)
   fmt.Printf("zuluType 的类型为:%v,类型名为:%v,种类为:%v\n", zuluType, zuluType.Name(), zuluType.Kind())
}
type Zulu struct {
   Name string
   Age int
}

执行上述代码,输出结果如下:

zuluType 的类型为:main.Zulu,类型名为:Zulu,种类为:struct

结构体变量的 反射类型对象 的 Name 就是结构体的名字,种类为 struct 结构体

指针的 反射类型对象

func main(){
   zulu := Zulu{"stark", 33}
   // 定义一个指针
   zuluPtr := &zulu
   zuluType := reflect.TypeOf(zuluPtr)
   fmt.Printf("zuluType 的类型为:%v,类型名为:%v,种类为:%v\n", zuluType, zuluType.Name(), zuluType.Kind())
}
type Zulu struct {
   Name string
   Age int
}

执行上述代码,输出结果如下:

zuluType 的类型为:*main.Zulu,类型名为:,种类为:ptr

指针的 Name() 返回的也是空字符串。

在 main 函数中增加代码

// 其余代码保持不变,在 main 函数底部增加如下代码。
// 使用反射类型对象(Type)获取原类型
zuluTypeElem := zuluType.Elem()
fmt.Printf("zuluTypeElem 的类型为:%v,类型名为:%v,种类为:%v\n", zuluTypeElem, zuluTypeElem.Name(), zuluTypeElem.Kind())

执行上述的代码,输出结果如下:

zuluType 的类型为:*main.Zulu,类型名为:,种类为:ptr
zuluTypeElem 的类型为:main.Zulu,类型名为:Zulu,种类为:struct

也就是说我们通过一个结构体指针获取了一个反射类型,在通过反射类型获取到原结构体

Go 中对指针获取 反射类型对象 之后,可以通过获取的 反射类型对象Elem 方法获取指针所执行的元素的类型,这个过程被称为取元素,就相当于对指针执行了 * 操作。

以上就是Go REFLECT Library反射类型详解的详细内容,更多关于Go REFLECT Library反射类型的资料请关注我们其它相关文章!

(0)

相关推荐

  • Go语言反射reflect.Value实现方法的调用

    目录 引言 func (Value) Call 通过反射,调用方法. 通过反射,调用函数. 引言 这算是一个高级用法了,前面我们只说到对类型.变量的几种反射的用法,包括如何获取其值.其类型.以及如何重新设置新值.但是在项目应用中,另外一个常用并且属于高级的用法,就是通过reflect来进行方法[函数]的调用.比如我们要做框架工程的时候,需要可以随意扩展方法,或者说用户可以自定义方法,那么我们通过什么手段来扩展让用户能够自定义呢?关键点在于用户的自定义方法是未可知的,因此我们可以通过reflect

  • Go利用反射reflect实现获取接口变量信息

    目录 引言 一.反射的规则 1.从实例到 Value 2.从实例到 Type 3.从 Type 到 Value 4.从 Value 到 Type 5.从 Value 到实例 6.从 Value 的指针到值 7.Type 指针和值的相互转换 8.Value 值的可修改性 9.根据 Go 官方关于反射的文档,反射有三大定律:9 二.反射的使用 1.已知原有类型 2.未知原有类型 总结 引言 反射是通过实体对象获取反射对象(Value.Type),然后可以操作相应的方法.在某些情况下,我们可能并不知道

  • 详解Golang利用反射reflect动态调用方法

    编程语言中反射的概念 在计算机科学领域,反射是指一类应用,它们能够自描述和自控制.也就是说,这类应用通过采用某种机制来实现对自己行为的描述(self-representation)和监测(examination),并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义. 每种语言的反射模型都不同,并且有些语言根本不支持反射.Golang语言实现了反射,反射机制就是在运行时动态的调用对象的方法和属性,官方自带的reflect包就是反射相关的,只要包含这个包就可以使用. 多插一句,

  • Go语言reflect.TypeOf()和reflect.Type通过反射获取类型信息

    在 Go语言中通过调用 reflect.TypeOf 函数,我们可以从一个任何非接口类型的值创建一个 reflect.Type 值.reflect.Type 值表示着此非接口值的类型.通过此值,我们可以得到很多此非接口类型的信息.当然,我们也可以将一个接口值传递给一个 reflect.TypeOf 函数调用,但是此调用将返回一个表示着此接口值的动态类型的 reflect.Type 值. 实际上,reflect.TypeOf 函数的唯一参数的类型为 interface{},reflect.Type

  • golang 如何用反射reflect操作结构体

    背景 需要遍历结构体的所有field 对于exported的field, 动态set这个field的value 对于unexported的field, 通过强行取址的方法来获取该值(tricky?) 思路 下面的代码实现了从一个strct ptr对一个包外结构体进行取值的操作,这种场合在笔者需要用到反射的场合中出现比较多 simpleStrtuctField 函数接受一个结构体指针,因为最后希望改变其值,所以传参必须是指针.然后解引用. 接下来遍历结构体的每个field, exported字段是

  • 深入理解Golang的反射reflect示例

    目录 编程语言中反射的概念 interface 和 反射 Golang的反射reflect reflect的基本功能TypeOf和ValueOf 说明 从relfect.Value中获取接口interface的信息 已知原有类型[进行“强制转换”] 说明 未知原有类型[遍历探测其Filed] 说明 通过reflect.Value设置实际变量的值 说明 通过reflect.ValueOf来进行方法的调用 说明 Golang的反射reflect性能 小结 总结 参考链接 编程语言中反射的概念 在计算

  • Go REFLECT Library反射类型详解

    目录 一.反射概述 二.反射类型对象 基本数类型的 反射类型对象 引用数据类型的 反射类型对象 结构体的 反射类型对象 指针的 反射类型对象 一.反射概述 反射是指程序在运行期间对程序本身进行访问和修改的能力.程序在编译过程中变量会被转换为内存地址,变量名不会被编译器写入到可执行部分.在程序运行时程序无法获取自身的信息. 在静态语言中如 Java 可以在程序编译期将变量的反射信息,如字段名称.类型等信息整合到可执行文件中,并给程序提供接口访问反射信息,这样就可以在程序运行期获取类型的反射信息,并

  • Java中的反射机制详解

    Java中的反射机制详解 反射,当时经常听他们说,自己也看过一些资料,也可能在设计模式中使用过,但是感觉对它没有一个较深入的了解,这次重新学习了一下,感觉还行吧! 一,先看一下反射的概念: 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义. 反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接.但是反射使用不当会成本很高! 看概念很晕的,继续往下

  • Java 反射机制详解及实例

    Java 反射机制详解及实例 反射,当时经常听他们说,自己也看过一些资料,也可能在设计模式中使用过,但是感觉对它没有一个较深入的了解,这次重新学习了一下,感觉还行吧!            一,先看一下反射的概念: 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义. 反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接.但是反射使用不当会成本很高

  • Java反射技术详解及实例解析

    前言 相信很多人都知道反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的,比如最初的很多注解框架,后来因为java反射影响性能,所以被运行时注解APT替代了,java反射有个开源框架jOOR相信很多人都用过,不过我们还是要学习反射的基础语法,这样才能自己写出优秀的框架,当然这里所讲的反射技术,是学习Android插件化技术.Hook技术等必不可少的! 一.基本反射技术   1.1 根据一个字符串得到一个类 getClass方法 String nam

  • Go语言基础反射示例详解

    目录 概述 语法 一.基本操作 二.修改目标对象 三.动态调用方法 总结 示例 概述 在程序运行期对程序动态的进行访问和修改 reflect godoc: https://golang.org/pkg/reflect/ reflect包有两个数据类型: Type:数据类型 [reflect.TypeOf():是获取Type的方法] Value:值的类型[reflect.ValueOf():是获取Value的方法] 语法 一.基本操作 获取变量类型 func TypeOf(i interface{

  • go语言reflect.Type 和 reflect.Value 应用示例详解

    目录 一.使用 reflect.Type 创建实例 二.使用 reflect.Value 调用函数 一.使用 reflect.Type 创建实例 在通过 reflect.TypeOf 函数获取到变量的反射类型对象之后,可以通过反射类型对象 reflect.Type 的 New 函数来创建一个新的实例,注意这个实例的类型是 reflect.Type 类型的. package main import ( "fmt" "reflect" ) func main() { v

  • Java动态代理和反射机制详解

    反射机制 Java语言提供的一种基础功能,通过反射,我们可以操作这个类或对象,比如获取这个类中的方法.属性和构造方法等. 动态代理:分为JDK动态代理.cglib动态代理(spring中的动态代理). 静态代理 预先(编译期间)确定了代理者与被代理者之间的关系,也就是说,若代理类在程序运行前就已经存在了,这种情况就叫静态代理 动态代理 代理类在程序运行时创建的代理方式.也就是说,代理类并不是在Java代码中定义的,而是在运行期间根据我们在Java代码中的"指示"动态生成的. 动态代理比

  • python ctypes库2_指定参数类型和返回类型详解

    python函数的参数类型和返回类型默认为int. 如果需要传递一个float值给dll,那么需要指定参数的类型. 如果需要返回一个flaot值到python中,那么需要指定返回数据的类型. 数据类型参考python文档: https://docs.python.org/3.6/library/ctypes.html#fundamental-data-types import ctypes path = r'E:\01_Lab\VisualStudioLab\cpp_dll\cpp_dll\De

  • Java基础篇之反射机制详解

    目录 1.反射概述 1.1什么是反射 1.2.反射能干什么 2.解剖类 2.1反射构造方法 2.1.1反射无参的构造函数 2.1.2反射“一个参数”的构造函数 2.1.3反射“多个参数”的构造函数 2.1.4反射“私有”的构造函数 2.1.5反射得到类中所有的构造函数 2.2反射类中的方法 2.3反射类中的属性字段 思考:在讲反射之前,先思考一个问题,java中如何创建一个对象,有哪几种方式? Java中创建对象大概有这几种方式: 1.使用new关键字:这是我们最常见的也是最简单的创建对象的方式

  • Swift进阶教程Mirror反射示例详解

    目录 元类型与.self AnyObject AnyClass Any type(Of:) self self在方法里面的作用 Self Swift Runtime Mirror Mirror的基本用法 Mirror的简单应用-JSON解析 Mirror源码解析 Enum Metadata探索 还原TargetEnumMetadata 还原TargetEnumDescriptor 相对偏移指针 打印枚举中的属性 Struct Metadata探索 获取结构体的属性 swift_getTypeBy

随机推荐