Go语言反射解析结构体 | 青训营笔记

119 阅读4分钟

Go语言反射解析结构体教程

在 Golang 中,通过 反射 的 reflect.TypeOf() 获得反射的对象信息后,如果是 结构体 类型,可以通过反射值对象(reflect.Type)的 NumField() 和 Field() 方法获得结构体成员的详细信息。

结构体成员访问的方法列表

方法说明
Field(i int) StructField根据索引,返回索引对应的结构体字段的信息。当值不是结构体或索引超界时会引发 pannic
NumField() int返回结构体成员字段数量。当类型不是结构体或索引超界时引发 pannic
FieldByName(name string) (StructField, bool)根据给定字符串返回字符串对应的结构体字段的信息。没有找到时 bool 返回 false,当类型不是结构体或索引超界时引发 pannic
FieldByIndex(index []int) StructField多层成员访问时,根据 []int 提供的每个结构体的字段索引,返回字段的信息。没有找到时返回零值。当类型不是结构体或索引超界时引发 pannic
FieldByNameFunc( match func(string) bool) (StructField,bool)根据匹配函数匹配需要的字段。当值不是结构体或索引超界时引发 pannic

Go语言反射StructField结构

reflect.Type 的 Field() 方法返回 StructField 结构,这个结构描述结构体的成员信息,通过这个信息可以获取成员与结构体的关系,如偏移、索引、是否为匿名字段、结构体标签(Struct Tag)等,而且还可以通过 StructField 的 Type 字段进一步获取结构体成员的类型信息。StructField 的结构如下:

type StructField struct {
    Name string          // 字段名
    PkgPath string       // 字段路径
    Type      Type       // 字段反射类型对象
    Tag       StructTag  // 字段的结构体标签
    Offset    uintptr    // 字段在结构体中的相对偏移
    Index     []int      // Type.FieldByIndex中的返回的索引值
    Anonymous bool       // 是否为匿名字段
}

案例

Go语言反射解析结构体

通过反射获取结构体的所有字段

package main
import (
	"fmt"
	"reflect"
)
type Person struct {
	Name string
	Age int
}
func main() {
	fmt.Println("嗨客网(www.haicoder.net)")
	person := Person{
		Name:"HaiCoder",
		Age:109,
	}
	personType := reflect.TypeOf(person)
	for i := 0; i < personType.NumField(); i++ {
		// 获取每个成员的结构体字段类型
		fieldType := personType.Field(i)
		// 输出字段名
		fmt.Println("FiledName =", fieldType.Name)
	}
}

程序运行后,控制台输出如下:

21_golang反射获取结构体字段.png

首先,我们定义了一个 Person 结构体,结构体含有两个字段,一个 字符串 类型的 Name 和一个 int 类型的 Age。

接着,我们使用 reflect.TypeOf 获取结构体的实例,并使用实例信息的 NumField() 获取字段总数,并使用 for循环 遍历每一个字段信息,通过字段信息的 Name 属性获取到每一个字段名。

Go语言反射获取结构体Tag

通过反射获取结构体的字段的 Tag

    package main
    import (
    	"fmt"
    	"reflect"
    )
    type Person struct {
    	Name string `json:name`
    	Age int `json:age`
    }
    func main() {
    	fmt.Println("嗨客网(www.haicoder.net)")
    	person := Person{
    		Name:"HaiCoder",
    		Age:109,
    	}
    	personType := reflect.TypeOf(person)
    	for i := 0; i < personType.NumField(); i++ {
    		// 获取每个成员的结构体字段类型
    		fieldType := personType.Field(i)
    		fmt.Println("FiledName =", fieldType.Name, "Type =", fieldType.Type, "Tag =", fieldType.Tag)
    	}
    }

程序运行后,控制台输出如下:

22_golang反射获取结构体字段.png

我们定义了一个包含 Tag 的结构体 Person,接着,我们使用 for 循环遍历结构体的每一个字段,通过 Filed 获取每一个字段的具体信息。

最后,我们通过结构体字段的 Name 属性获取字段名,通过 Type 属性获取字段的类型,通过 Tag 获取字段的标签信息。

Go语言反射获取字段信息

Go语言通过反射获取指定字段的具体信息


        package main
        import (
        	"fmt"
        	"reflect"
        )
        type Person struct {
        	Name string `json:name`
        	Age int `json:age`
        }
        func main() {
        	fmt.Println("嗨客网(www.haicoder.net)")
        	person := Person{
        		Name:"HaiCoder",
        		Age:109,
        	}
        	personType := reflect.TypeOf(person)
        	filedName, isOk := personType.FieldByName("Name")
        	if isOk{
        		fmt.Println("FiledName =", filedName.Name, "Type =", filedName.Type, "Tag =", filedName.Tag)
        	}else{
        		fmt.Println("Filed Name not exist")
        	}
        }

程序运行后,控制台输出如下:

23_golang反射获取结构体字段.png

我们通过 reflect.TypeOf 获取了结构体的实例信息后,再通过 FieldByName 方法可以获取指定字段名的字段信息。

Go语言反射解析结构体总结

在 Golang 中,通过反射的 reflect.TypeOf() 获得反射的对象信息后,如果是结构体类型,可以通过反射值对象(reflect.Type)的 NumField() 和 Field() 方法获得结构体成员的详细信息。

参考

Go语言反射解析结构体-Go语言反射获取结构体Tag-Go语言反射获取结构体字段-嗨客网 (haicoder.net)