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

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

实际上,reflect.TypeOf 函数的唯一参数的类型为 interface{},reflect.TypeOf 函数将总是返回一个表示着此唯一接口参数值的动态类型的 reflect.Type 值。

那如何得到一个表示着某个接口类型的 reflect.Type 值呢?我们必须通过下面将要介绍的一些间接途径来达到这一目的。

类型 reflect.Type 为一个接口类型,它指定了若干方法(https://golang.google.cn/pkg/reflect/#Type)。 通过这些方法,我们能够观察到一个 reflect.Type 值所表示的 Go类型的各种信息。这些方法中的有的适用于所有种类(https://golang.google.cn/pkg/reflect/#Kind)的类型,有的只适用于一种或几种类型。通过不合适的 reflect.Type 属主值调用某个方法将在运行时产生一个恐慌。

使用 reflect.TypeOf() 函数可以获得任意值的类型对象(reflect.Type),程序通过类型对象可以访问任意值的类型信息。下面通过例子来理解获取类型对象的过程:

package main
import (
    "fmt"
    "reflect"
)
func main() {
    var a int
    typeOfA := reflect.TypeOf(a)
    fmt.Println(typeOfA.Name(), typeOfA.Kind())
}

代码输出如下:
int  int

代码说明如下:

  • 第 10 行,定义一个 int 类型的变量。
  • 第 12 行,通过 reflect.TypeOf() 取得变量 a 的类型对象 typeOfA,类型为 reflect.Type()。
  • 第 14 行中,通过 typeOfA 类型对象的成员函数,可以分别获取到 typeOfA 变量的类型名为 int,种类(Kind)为 int。

理解反射的类型(Type)与种类(Kind)

在使用反射时,需要首先理解类型(Type)和种类(Kind)的区别。编程中,使用最多的是类型,但在反射中,当需要区分一个大品种的类型时,就会用到种类(Kind)。例如,需要统一判断类型中的指针时,使用种类(Kind)信息就较为方便。

1) 反射种类(Kind)的定义

Go 程序中的类型(Type)指的是系统原生数据类型,如 int、string、bool、float32 等类型,以及使用 type 关键字定义的类型,这些类型的名称就是其类型本身的名称。例如使用 type A struct{} 定义结构体时,A 就是 struct{} 的类型。

种类(Kind)指的是对象归属的品种,在 reflect 包中有如下定义:

type Kind uint
const (
    Invalid Kind = iota  // 非法类型
    Bool                 // 布尔型
    Int                  // 有符号整型
    Int8                 // 有符号8位整型
    Int16                // 有符号16位整型
    Int32                // 有符号32位整型
    Int64                // 有符号64位整型
    Uint                 // 无符号整型
    Uint8                // 无符号8位整型
    Uint16               // 无符号16位整型
    Uint32               // 无符号32位整型
    Uint64               // 无符号64位整型
    Uintptr              // 指针
    Float32              // 单精度浮点数
    Float64              // 双精度浮点数
    Complex64            // 64位复数类型
    Complex128           // 128位复数类型
    Array                // 数组
    Chan                 // 通道
    Func                 // 函数
    Interface            // 接口
    Map                  // 映射
    Ptr                  // 指针
    Slice                // 切片
    String               // 字符串
    Struct               // 结构体
    UnsafePointer        // 底层指针
)

Map、Slice、Chan 属于引用类型,使用起来类似于指针,但是在种类常量定义中仍然属于独立的种类,不属于 Ptr。

type A struct{} 定义的结构体属于 Struct 种类,*A 属于 Ptr。

2) 从类型对象中获取类型名称和种类的例子

Go语言中的类型名称对应的反射获取方法是 reflect.Type 中的 Name() 方法,返回表示类型名称的字符串。

类型归属的种类(Kind)使用的是 reflect.Type 中的 Kind() 方法,返回 reflect.Kind 类型的常量。

下面的代码中会对常量和结构体进行类型信息获取。

package main
import (
    "fmt"
    "reflect"
)
// 定义一个Enum类型
type Enum int
const (
    Zero Enum = 0
)
func main() {
    // 声明一个空结构体
    type cat struct {
    }
    // 获取结构体实例的反射类型对象
    typeOfCat := reflect.TypeOf(cat{})
    // 显示反射类型对象的名称和种类
    fmt.Println(typeOfCat.Name(), typeOfCat.Kind())
    // 获取Zero常量的反射类型对象
    typeOfA := reflect.TypeOf(Zero)
    // 显示反射类型对象的名称和种类
    fmt.Println(typeOfA.Name(), typeOfA.Kind())
}

代码输出如下:
cat struct
Enum int

代码说明如下:

  • 第 18 行,声明结构体类型 cat。
  • 第 22 行,将 cat 实例化,并且使用 reflect.TypeOf() 获取被实例化后的 cat 的反射类型对象。
  • 第 25 行,输出cat的类型名称和种类,类型名称就是 cat,而 cat 属于一种结构体种类,因此种类为 struct。
  • 第 28 行,Zero 是一个 Enum 类型的常量。这个 Enum 类型在第 9 行声明,第 12 行声明了常量。如没有常量也不能创建实例,通过 reflect.TypeOf() 直接获取反射类型对象。
  • 第 31 行,输出 Zero 对应的类型对象的类型名和种类。

到此这篇关于Go语言reflect.TypeOf()和reflect.Type通过反射获取类型信息 的文章就介绍到这了,更多相关Go 反射获取类型信息 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Go语言-为什么返回值为接口类型,却返回结构体

    最近由于项目需求,阅读一些Go语言编写的项目的源代码,在某一个函数中发现了一个奇怪的现象:一个函数的返回值类型声明的是一个接口的类型,但是实际在函数体内返回的却是一个结构体类型的对象. 这个现象对于新手的我来说很是费解.在经过一些资料的查阅之后,自己得到了如下的解释: 一个结构体实现了一个接口,那么函数中返回值类型为接口时,就应该返回这个结构体. 下面举一个例子来说明: package main import ( "fmt" ) /** Shape接口定义两个函数: area() :计

  • Go语言编译程序从后台运行,不出现dos窗口的操作

    命令: go build -ldflags "-H windowsgui" 编译文件.go 例如: go build -ldflags "-H windowsgui" main.go 常用参数: -o "chen.exe" 增加此参数则编译后的输出文件名称改为chen.exe 补充:golang 常用快捷键,编译linux程序参数设置,编译不显示DOS窗口命令 整理下个人在开发过程中常用的快捷键: Debugging 单步进入 F7 单步越过 F

  • Go语言操作数据库及其常规操作的示例代码

    Go操作MySQL 安装: go get -u github.com/go-sql-driver/mysql GO语言的操作数据库的驱动原生支持连接池, 并且是并发安全的 标准库没有具体的实现 只是列出了一些需要的第三方库实现的具体内容 //第一次连接MySQL成功 package main import ( "database/sql" _ "github.com/go-sql-driver/mysql" // _想当于init()初始化 "log&qu

  • go语言实现简易比特币系统之交易签名及校验功能

    介绍 签名的输入: 待签名的交易数据,包括输入和输出 引用的UTXO信息 私钥 签名的输出: 数字数字签名 公钥 签名的目的 证明交易所引用的UTXO的确属于付款人 证明交易的所有数据的确是付款人提供的,且未被修改过 签名中需要的数据 UTXO中的PubKeyHash,这描述了付款人 新生成UTXO中的PubKeyHash,这描述了收款人 由于每一笔交易都可能引用多个UTXO,因为多个UTXO可能存在于多条交易中.所以我们需要遍历所以的引用交易,并对他们逐个签名 签名过程 用解锁脚本解锁对应的U

  • 详解用Go语言实现工厂模式(Golang经典编程案例)

    golang中的struct没有构造函数,一般可以使用工厂模式来解决这个问题.这个模式本身很简单而且使用在业务较简单的情况下.一般用于小项目或者具体产品很少扩展的情况(这样工厂类才不用经常更改). 代码结构如下:分别有main.go和student.go两个文件. 在student.go中: package model //定义一个结构体 type student struct{ Name string score float64 } //因为student结构体首字母是小写,因此是只能在mod

  • go语言静态库的编译和使用方法

    本文主要介绍go语言静态库的编译和使用方法,以windows平台为例,linux平台步骤一样,具体环境如下: >echo %GOPATH% E:\share\git\go_practice\ >echo %GOROOT% C:\Go\ >tree /F %GOPATH%\src 卷 work 的文件夹 PATH 列表 卷序列号为 0009-D8C8 E:\SHARE\GIT\GO_PRACTICE\SRC │ main.go │ └─demo demo.go 在%GOPATH%\src目

  • Go语言利用ssh连接服务器的方法步骤

    学习了Go语言后,打算利用最近比较空一点,写一个前端部署工具,不需要每次都复制粘贴的麻烦,需要完成部署的第一步就需要连接远程服务器 打开 ssh server 首先我们想要利用ssh连接服务器的前提是服务器打开了ssh server,ssh 分为client和server端 ,如果打开了client可以连接远程服务器,打开了server就可以被连接. 因为linux网上教程很多,windows比较少,所以这里只写windows版本的, 首先我们一般用Open SSH这个工具打开服务,window

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

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

  • Go语言反射获取类型属性和方法示例

    本系列文章,我将会进一步加深对 Go 语言的讲解,更一步介绍 Go 中的包管理.反射和并发等高级特性. 前面一篇文章主要介绍了 reflect.Type 类型对象.本文将会继续介绍 Go 反射 reflect.StructField 和 reflect.Method 相关的内容. reflect.StructField 和 reflect.Method 如果变量是一个结构体,我们还可以通过结构体域类型对象 reflect.StructField 来获取结构体下字段的类型属性.Type 接口下提供

  • go语言通过反射获取和设置结构体字段值的方法

    本文实例讲述了go语言通过反射获取和设置结构体字段值的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: type MyStruct struct {         N int } n := MyStruct{ 1 } // get immutable := reflect.ValueOf(n) val := immutable.FieldByName("N").Int() fmt.Printf("N=%d\n", val) // prints

  • Go语言扫描目录并获取相关信息的方法

    本文实例讲述了Go语言扫描目录并获取相关信息的方法.分享给大家供大家参考.具体分析如下: 前言:最近看到Go里面有一个func很容易就可以扫描整个目录,并且可以得到相应的目录和文件信息,所以我将其进行了封装,拿到file info的所有信息 这样就可以方便的做其它用途了. 直接上代码,代码基于Go version 1 复制代码 代码如下: package main import (     "path/filepath"     "os"     "fla

  • 基于Jquery Ajax type的4种类型(详解)

    Ajax type这个里面填什么呢?通常大家都会说get和post.那么还有2个是什么呢? $.ajax({ url: 'http://www.cnblogs.com/youku/', type: '', data: {} }); (默认: "GET") 请求方式 ("POST" 或 "GET"), 默认为 "GET".注意:其它 HTTP 请求方法,如 PUT 和 DELETE 也可以使用,但仅部分浏览器支持. 此处是网上找

  • C语言实现获取内存信息并输出的实例

    C语言实现获取内存信息并输出的实例 实现实例代码: headfile.h #include <stdio.h> #include <stdlib.h> #include <time.h> #define TRUE 1 #define FALSE 0 #define MAX 10000 typedef int KeyType; typedef int OtherType; typedef struct { KeyType key; OtherType other_data

  • 深入浅析Python获取对象信息的函数type()、isinstance()、dir()

    type()函数: 使用type()函数可以判断对象的类型,如果一个变量指向了函数或类,也可以用type判断. 如: class Student(object): name = 'Student' a = Student() print(type(123)) print(type('abc')) print(type(None)) print(type(abs)) print(type(a)) 运行截图如下: 可以看到返回的是对象的类型. 我们可以在if语句中判断比较两个变量的type类型是否相

  • 解决C语言中使用scanf连续输入两个字符类型的问题

    昨天用C编程,遇到一个关于scanf的细节问题,假如运行如下程序: #include<stdio.h> int main() { char ch1,ch2; printf("Input for ch1:/n"); scanf("%c",&ch1); printf("ch1=%c/n",ch1); printf("Input for ch2:/n"); scanf("%c",&ch

  • C语言操作符进阶教程(表达式求值隐式类型转换方法)

    目录 结构体 表达式求值 隐式类型转换 意义: 方法 算术转换 操作符属性 结构体 结构体变量的声明需要在主函数之上或者主函数中声明,如果在主函数之下则会报错,而且c语言中的结构体不能直接进行强制转换,只有结构体指针才能进行强制转换. 涉及结构体的操作符这里讲两个:. (结构体访问操作符)-> () 首先写一段代码: int main() { struct Stu s = {"me",19,60}; prinft("%s %d %lf",s.who,s.age

  • vue props type设置多个类型

    目录 props type设置多个类型 vue定义props props type设置多个类型 props: { value: { // vue props type设置多个类型 type: Number | null, required: true }, articleId: { type: [Number, String, Object], required: true } }, vue定义props props: { num: { type: [Number, String], //支持多

随机推荐