前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go REFLECT Library | 02 - 反射的类型 Type

Go REFLECT Library | 02 - 反射的类型 Type

作者头像
RiemannHypothesis
发布2022-09-28 16:17:19
2770
发布2022-09-28 16:17:19
举报
文章被收录于专栏:ElixirElixir

本文紧接 Go REFLECT Library | 01 - 反射的类型 Type 继续讲解通过指针的 反射类型对象 获取了指针指向的对象之后的操作

三、反射获取结构体

在通过指针的 反射类型对象 获取了指针指向的对象之后,我们就可以对这个对象进行一些操作或者获取对象信息。

指针的 反射类型对象 获取指针指向的对象的类型如果是结构体,可以通过 反射类型对象reflect.Type 的一个方法来获取结构体成员信息,比如

方法

方法说明

Field(i int) StructField

通过索引获取结构体中对应的字段,当不是结构体或者索引越界会 panic

NumField() int

获取结构体中包含的字段的数量,不是结构体会 panic

FieldByName(name string) (StrucField, bool)

根据给定的字符串返回字符串对应的结构体字段的信息,没有找到时 bool 为 false, 当不是结构体或者索引越界会 panic

FieldByIndex(index []int) StructField

针对嵌套结构体,多层访问时,根据 []int 提供的每个结构体的索引依次访问,返回字段信息,没有找到返回零值,当不是结构体或者索引越界会 panic

FieldByNameFunc(match func(string) bool) (StructField, bool)

根据匹配函数匹配需要的字段,当不是结构体或者索引越界会 panic

代码语言:javascript
复制
func main(){

   zulu := Zulu{"stark", 33}

   zuluPtr := &zulu

   zuluType := reflect.TypeOf(zuluPtr)

   fmt.Printf("zuluType 的类型为:%v,类型名为:%v,种类为:%v\n", zuluType, zuluType.Name(), zuluType.Kind())

   // 使用反射类型对象(Type)获取指针指向的对象
   zuluStructByReflect := zuluType.Elem()

   fmt.Printf("zuluStructByReflect 的类型为:%v,类型名为:%v,种类为:%v\n", zuluStructByReflect, zuluStructByReflect.Name(), zuluStructByReflect.Kind())

   // 结构体字段的数量
   numField := zuluStructByReflect.NumField()
   fmt.Println("反射类型对象获取的指针指向的对象的字段数量有:", numField)

   // 获取第一个字段
   firstField := zuluStructByReflect.Field(0)
   fmt.Printf("第一个字段是:%v, 类型是: %v", firstField, (reflect.TypeOf(firstField)).Name())
}

type Zulu struct {
   Name string
   Age int
}

执行上述代码,输出结果如下:

代码语言:javascript
复制
zuluType 的类型为:*main.Zulu,类型名为:,种类为:ptr
zuluStructByReflect 的类型为:main.Zulu,类型名为:Zulu,种类为:struct
反射类型对象获取的指针指向的对象的字段数量有: 2
第一个字段是:{Name  string  0 [0] false}, 类型是: StructField

zuluPtr 结构体指针指向的结构体有两个字段,并且在调用 Field(0) 方法时返回一个 StructField 结构体,该结构体包含的字段如下:

image.png
image.png

其中:

  • Name:字段名称
  • PkgPath:字段在结构体中的路径
  • Type:字段本身的反射类型对象,类型为 reflect.Type 可以进一步获取字段的类型信息
  • Tag:结构体标签
  • Index:FieldByIndex 中的索引顺序
  • Anonymous:表示该字段是否为匿名字段
代码语言:javascript
复制
func main(){

   t := Teacher{"Stark", 33, "NYC"}

   s := Stu{"Peter", 18, "HighSchool","M", t}

   sPtr := &s

   sReflectType := reflect.TypeOf(sPtr)

   fmt.Printf("sReflectType 的类型为:%v,类型名为:%v,种类为:%v\n", sReflectType, sReflectType.Name(), sReflectType.Kind())

   // 使用反射类型对象(Type)获取指针指向的对象
   sStructByReflect := sReflectType.Elem()

   fmt.Printf("sStructByReflect 的类型为:%v,类型名为:%v,种类为:%v\n", sStructByReflect, sStructByReflect.Name(), sStructByReflect.Kind())

   // 结构体字段的数量
   numField := sStructByReflect.NumField()
   fmt.Println("反射类型对象获取的指针指向的对象的字段数量有:", numField)

   // 遍历所有的字段
   for i := 0; i < numField; i++ {
      field := sStructByReflect.Field(i)
      fmt.Printf("结构体的第 %v 个字段为:%v\n", (i+1), field.Name)
   }

   // 获取内嵌结构体 Teacher 的字段
   embedFieldByIndex := sStructByReflect.FieldByIndex([]int{4, 2})
   fmt.Println("结构体字段的名称为:", embedFieldByIndex.Name)
   fmt.Println("结构体字段的路径为:", embedFieldByIndex.PkgPath)
   fmt.Println("结构体字段的类型为:", embedFieldByIndex.Type)
   fmt.Println( "结构体字段的标签为:",embedFieldByIndex.Tag)
   fmt.Println("结构体字段的索引为:", embedFieldByIndex.Index)
   fmt.Println( "结构体字段的是否为匿名:",embedFieldByIndex.Anonymous)
}

type Stu struct {
   Name string `json:"name"`
   Age int `json:"age"`
   Grade string `json:"grade"`
   Gender string `json:"gender"`
   Teacher
}

type Teacher struct {
   Name string `json:"name"`
   Age int `json:"age"`
   Address string `json:"address"`
}

执行上述代码,输出结果如下:

代码语言:javascript
复制
sReflectType 的类型为:*main.Stu,类型名为:,种类为:ptr
sStructByReflect 的类型为:main.Stu,类型名为:Stu,种类为:struct
反射类型对象获取的指针指向的对象的字段数量有: 5
结构体的第 1 个字段为:Name
结构体的第 2 个字段为:Age
结构体的第 3 个字段为:Grade
结构体的第 4 个字段为:Gender
结构体的第 5 个字段为:Teacher
结构体字段的名称为: Address
结构体字段的路径为: 
结构体字段的类型为: string
结构体字段的标签为: json:"address"
结构体字段的索引为: [2]
结构体字段的是否为匿名: false

Go 编程 | 连载 17 - 结构体方法 中提到了使用 reflect 包获取结构体标签,其实就是使用了 StructField 结构体的 Tag 字段来获取的。

标签在序列化和反序列化以及对象关系映射时都会用到结构体标签,字段调用 Tag 表返回一个 StructTag 类型

image.png
image.png

StructTag 类型的 Get 方法可以获取指定标签的内容。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 三、反射获取结构体
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档