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

 更新时间:2022年06月17日 11:22:43   作者:aoho  
这篇文章主要为大家介绍了本文将介绍 Go 反射 reflect.StructField 和 reflect.Method 相关的内容,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

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
	// 成员字段 Type
	Type      Type
	// Tag
	Tag       StructTag
	// 字节偏移
	Offset    uintptr
	// 成员字段的 index
	Index     []int
	// 成员字段是否公开
	Anonymous bool
}

StructField

StructField 中提供了 Type 用于获取字段的的类型信息,而 StructTag 一般用来描述结构体成员字段的额外信息,比如在 JSON 进行序列化和对象映射时会被使用。StructTag 一般由一个或者多个键值对组成,一个简单的例子如下:

ID string `json:"id"`

键与值使用 : 分隔,值用 "" 括起来, 键值对之间使用空格分隔。上面例子中说明 ID 字段在 JSON 序列化时会被变成 id 。

遍历 Hero 结构体

接下来,我们通过遍历 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 string
field' name is Age, type is int, kind is int
field' name is Speed, type is int, kind is int
field' name is Name, type is string, kind is string

上述代码中先使用 Type#NumField 获取 Hero 结构体中字段的数量,再通过 typeOfHero#Field 根据 index 获取每个字段域类型对象并打印它们的类型信息。代码最后还演示如何通过 typeOfHero#FieldByName 获取了字段名为 Name 的字段域类型对象。

Method

除了获取结构体下的字段域类型对象,Type 还提供方法获取接口下方法的方法类型对象 Method,接口方法描述如下:

	// 根据 index 查找方法
	Method(int) Method
	// 根据方法名查找方法
	MethodByName(string) (Method, bool)
	// 获取类型中公开的方法数量
	NumMethod() int

获取到的方法类型描述对象 Method 描述了方法的基本信息,包括方法名,方法类型等,代码如下所示:

type Method struct {
	// 方法名
	Name    string
	// 方法类型
	Type  Type
	// 反射对象,可用于调用方法
	Func  Value
	// 方法的index
	Index 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 语言的反射基础 reflect.StructField 和 reflect.Method。通过反射,我们可以拿到类型信息和定义的方法等,Go 的反射实现了反射的大多数功能,获取类型信息需要配合使用标准库中的词法、语法解析器和抽象语法数对源码进行扫描。下一篇文章将会继续介绍 Go 语言的反射 reflect.Value 反射值对象相关内容。

以上就是Go语言反射获取类型属性和方法示例的详细内容,更多关于Go反射获取类型属性方法的资料请关注脚本之家其它相关文章!

相关文章

  • 解决goland中编辑tpl文件不高亮没智能补全的问题

    解决goland中编辑tpl文件不高亮没智能补全的问题

    这篇文章主要介绍了解决goland中编辑tpl文件不高亮没智能补全的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Go1.21新增maps包的用法详解

    Go1.21新增maps包的用法详解

    maps 包提供了几个非常有用的用于操作 map 类型(任何类型的 map)的函数,本文为大家整理了部分函数的具体用法,感兴趣的小伙伴可以了解一下
    2023-08-08
  • golang API请求队列的实现

    golang API请求队列的实现

    本文主要介绍了golang API请求队列的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • 破解IDEA(Goland)注册码设置 license server一直有效不过期的过程详解

    破解IDEA(Goland)注册码设置 license server一直有效不过期的过程详解

    这篇文章主要介绍了破解IDEA(Goland)注册码设置 license server一直有效不过期,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • Golang中的new()和make()函数本质区别

    Golang中的new()和make()函数本质区别

    在 Go 语言开发中,new() 和 make() 是两个容易让开发者感到困惑的内建函数,尽管它们都用于内存分配,但其设计目的、适用场景和底层实现存在本质差异,本文将通过类型系统、内存模型和编译器实现三个维度,深入解析这两个函数的本质区别,感兴趣的朋友一起看看吧
    2025-02-02
  • 使用go操作redis的有序集合(zset)

    使用go操作redis的有序集合(zset)

    这篇文章主要介绍了使用go操作redis的有序集合(zset),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Golang打印复杂结构体两种方法详解

    Golang打印复杂结构体两种方法详解

    在 Golang 语言开发中,我们经常会使用结构体类型,如果我们使用的结构体类型的变量包含指针类型的字段,我们在记录日志的时候,指针类型的字段的值是指针地址,将会给我们 debug 代码造成不便
    2022-10-10
  • 详解如何在Go语言中循环数据结构

    详解如何在Go语言中循环数据结构

    这篇文章主要为大家详细介绍了如何在Go语言中循环数据结构(循环字符串、循环map结构和循环Struct),文中的示例代码代码讲解详细,需要的可以参考一下
    2022-10-10
  • 使用Go进行单元测试的实现

    使用Go进行单元测试的实现

    这篇文章主要介绍了使用Go进行单元测试的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • Go语言的接口详解

    Go语言的接口详解

    这篇文章主要介绍了go语言的接口,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧,希望能够给你带来帮助
    2021-10-10

最新评论