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

本文介绍了Go语言中反射的重要概念,包括如何通过`reflect.TypeOf()`获取非接口类型或接口值的动态类型的`reflect.Type`值。通过`Type`对象,我们可以获取类型名称和种类(Kind)。示例代码展示了如何获取结构体和常量的类型信息。在Go的反射系统中,`Kind`用于区分不同类型的品种,如基本类型、结构体、指针等。理解这些概念对于进行动态类型检查和操作至关重要。
摘要由CSDN通过智能技术生成

在 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 对应的类型对象的类型名和种类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值