Go学习(二十七):反射使用
文章目录
【注意】最后更新于 March 4, 2023,文中内容可能已过时,请谨慎使用。
1.介绍
Go
语言实现了反射,所谓反射就是动态运行时的状态。我们一般用到的包是reflect
包,reflect
实现了运行时的反射能力,能够让程序操作不同类型的对象。反射包中有两对非常重要的函数和类型,两个函数分别是:
方法名 | 描述 |
---|---|
reflect.TypeOf |
可以获得任意值的类型对象,返回类型:reflect.Type |
reflect.ValueOf |
可以获得任意值的值对象,返回类型:reflect.Value |
反射包中的所有方法基本都是围绕着
reflect.Type
和reflect.Value
两个类型设计的。我们通过reflect.TypeOf
、reflect.ValueOf
可以将一个普通的变量转换成反射包中提供的reflect.Type
和reflect.Value
,随后就可以使用反射包中的方法对它们进行复杂的操作。
2.reflect.Type
类型 reflect.Type
是反射包定义的一个接口,我们可以使用 reflect.TypeOf
函数获取任意变量的类型,reflect.Type
接口中定义了一些方法,常用的如下:
2.1 常用方法列表
方法名 | 描述 |
---|---|
Kind() Kind |
返回该变量的的具体分类 |
Name() string |
Name返回该类型在自身包内的类型名,如果是未命名类型会返回"" |
NumField() int |
返回 struct 字段数量,不是 struct 会 panic |
Implements(u Type) bool |
检查当前类型有没有实现接口 u |
Field(i int) StructField |
返回struct 类型的第 i 个字段,不是struct 会 panic ,i 越界也会panic |
Key() Type |
返回map 的key 的类型,不是map 会panic |
2.2 使用示例
|
|
2.3 Kind类型整理
|
|
3.reflect.Value
反射包中Value
的类型与Type
不同,它被声明成了结构体。这个结构体没有对外暴露的字段,但是提供了获取或者写入数据的方法。
3.1 常用方法列表
方法名 | 描述 |
---|---|
Call(in []Value) []Value |
调用方法,第一个参数是in[0] ,第二个是in[1] ,以此类推 |
Field(i int) StructField |
返回struct 类型的第 i 个字段的值,不是struct 会 panic ,i 越界也会panic 。 |
FieldByName(name string) Value |
根据字段名查找值,前提类型是struct |
Index(i int) Value |
返回第 i 个元素,主要用于遍历,不能越界。前提类型是 Array, Slice, String 之一, |
IsNil() bool |
返回值是否为nil 。如果值类型不是通道(channel )、函数、接口、 map 、指针或 切片时发生panic ,类似于语言层的v== nil 操作。常被用于判断指针是否为空。 |
IsValid() bool |
返回v是否持有一个值。如果v 是Value 零值会返回假,此时v除了IsValid、String、Kind之外的方法都会导致panic 。常被用于判定返回值是否有效 |
MapIndex(key Value) Value |
根据索引获取对应的值,前提类型是map |
MapKeys() []Value |
返回map 中所有的key ,返回类型是切片slice |
Set(x Value) |
通过反射修改值。 |
Type() Type |
获取值的类型 |
3.2 使用示例
|
|
输出:
|
|
4.实践场景
4.1 动态调用结构体方法
使用MethodByName("xx").Call(param)
调用函数
|
|
4.2 处理错误结果
|
|
4.3 解析结构体标签
使用field.Tag.Lookup()
或field.Tag.Get()
查找对应的标签值
|
|
4.4 判断是否实现接口
|
|
文章作者 Learn Go
上次更新 2023-03-04