怎么使用Go语言反射获取类型属性
本篇内容主要讲解“怎么使用Go语言反射获取类型属性”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用Go语言反射获取类型属性”吧!
reflect.StructField 和 reflect.Method
如果变量是一个结构体,我们还可以通过结构体域类型对象 reflect.StructField 来获取结构体下字段的类型属性。Type 接口下提供了不少用于获取字段结构体域类型对象的方法,我们主要介绍以下几个接口:
// 获取一个结构体内的字段数量NumField() int// 根据 index 获取结构体内的成员字段类型对象Field(i int) StructField// 根据字段名获取结构体内的成员字段类型对象FieldByName(name string) (StructField, bool)
通过以上的 3 个方法,我们可以轻易地拿到一个结构体变量内的所有成员字段的类型对象 reflect.StructField。通过 reflect.StructField,我们可以知道成员字段所属的类型和种类,其内主要由以下的属性:
type StructField struct {// 成员字段的名称Name string// 成员字段 TypeType Type// TagTag StructTag// 字节偏移Offset uintptr// 成员字段的 indexIndex []int// 成员字段是否公开Anonymous bool}
StructField 中提供了 Type 用于获取字段的的类型信息,而 StructTag 一般用来描述结构体成员字段的额外信息,比如在 JSON 进行序列化和对象映射时会被使用。StructTag 一般由一个或者多个键值对组成,一个简单的例子如下:
ID string `json:"id"`
键与值使用 : 分隔,值用 "" 括起来, 键值对之间使用空格分隔。上面例子中说明 ID 字段在 JSON 序列化时会被变成 id 。
接下来,我们通过遍历 Hero 结构体,获取其内字段的类型并输出,代码如下所示:
func main() {typeOfHero := reflect.TypeOf(Hero{})// 通过 #NumField 获取结构体字段的数量for i := 0 ; i < typeOfHero.NumField(); i++{fmt.Printf("field' name is %s, type is %s, kind is %s\n", typeOfHero.Field(i).Name, typeOfHero.Field(i).Type, typeOfHero.Field(i).Type.Kind())}// 获取名称为 Name 的成员字段类型对象nameField, _ := typeOfHero.FieldByName("Name")fmt.Printf("field' name is %s, type is %s, kind is %s\n", nameField.Name, nameField.Type, nameField.Type.Kind())}
预期的结果如下所示:
field' name is Name, type is string, kind is stringfield' name is Age, type is int, kind is intfield' name is Speed, type is int, kind is intfield' name is Name, type is string, kind is string
上述代码中先使用 Type#NumField 获取 Hero 结构体中字段的数量,再通过 typeOfHero#Field 根据 index 获取每个字段域类型对象并打印它们的类型信息。代码最后还演示如何通过 typeOfHero#FieldByName 获取了字段名为 Name 的字段域类型对象。
除了获取结构体下的字段域类型对象,Type 还提供方法获取接口下方法的方法类型对象 Method,接口方法描述如下:
// 根据 index 查找方法Method(int) Method// 根据方法名查找方法MethodByName(string) (Method, bool)// 获取类型中公开的方法数量NumMethod() int
获取到的方法类型描述对象 Method 描述了方法的基本信息,包括方法名,方法类型等,代码如下所示:
type Method struct {// 方法名Name string// 方法类型Type Type// 反射对象,可用于调用方法Func Value// 方法的indexIndex int}
在 Method 中 Func 字段是一个反射值对象,可用于进行方法的调用。如果 Method 是来自于接口类型反射得到的 Type ,那么 Func 传递的第一个参数需要为实现方法的接收器,这部分区别我们将在 Value 中进行具体的介绍。
我们可以通过 Type 中提供的方法获取接口 Person 中方法的方法类型对象,代码如下所示:
func main() {// 声明一个 Person 接口,并用 Hero 作为接收器var person Person = &Hero{}// 获取接口Person的类型对象typeOfPerson := reflect.TypeOf(person)// 打印Person的方法类型和名称for i := 0 ; i < typeOfPerson.NumMethod(); i++{fmt.Printf("method is %s, type is %s, kind is %s.\n", typeOfPerson.Method(i).Name, typeOfPerson.Method(i).Type, typeOfPerson.Method(i).Type.Kind())}method, _ := typeOfPerson.MethodByName("Run")fmt.Printf("method is %s, type is %s, kind is %s.\n", method.Name, method.Type, method.Type.Kind())}
预期的输出结果如下所示:
method is Run, type is func(*main.Hero), kind is func
method is SayHello, type is func(*main.Hero, string), kind is func
method is Run, type is func(*main.Hero) string, kind is func.
除了通过 typeOfPerson#Method 根据 index 获取方法类型对象,还可以使用 typeOfPerson#MethodByName 根据方法名查找对应的方法类型对象。从输出结果可以看出,方法的种类均为 func,而类型则为方法的声明。
到此,相信大家对“怎么使用Go语言反射获取类型属性”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341