反射操作结构体-获取对象信息
获取对象信息
Golang解析结构体标签主要通过反射实现。除上述章节反复使用到的 Typeof()、ValueOf()、Kind()等方法外,还要借助reflect包中的其他方法:
func (v [Value](#Value)) NumField() [int](#int)
返回v持有的结构体类型值的字段数,如果v的Kind不是Struct会panic
func (v Value) Type() Type
返回v持有的值的类型的Type表示。
而Type 是一个interface,包含方法 Field(i int) StructField 返回StructField结构体类型。
StructField类型描述结构体中的一个字段的信息。
type StructField struct {
// Name是字段的名字。PkgPath是非导出字段的包路径,对导出字段该字段为""。
// 参见http://golang.org/ref/spec#Uniqueness_of_identifiers
Name string
PkgPath string
Type Type // 字段的类型
Tag StructTag // 字段的标签
Offset uintptr // 字段在结构体中的字节偏移量
Index []int // 用于Type.FieldByIndex时的索引切片
Anonymous bool // 是否匿名字段
}
StructTag是结构体字段的标签。
type StructTag string
Get方法返回标签字符串中键key对应的值。如果标签中没有该键,会返回""。
func (tag StructTag) Get(key string) string
package main
import (
"fmt"
"reflect"
)
const tagName = "Testing"
type Test struct {
Name string `json:"-"` //“-”作用是不进行序列化,效果和将结构体字段写成小写一样。
Age int `json:"age,omitempty"` // “omitempty”作用是在序列化的时候忽略0值或空值。
Id int `json:"idx,string"` // 序列化时,类型转化为string
Sex string `json:"sex"`
}
func main() {
test := Test{"kitty", 18, 61, "female"}
//通过反射,我们获取变量的动态类型
reType := reflect.TypeOf(test)
fmt.Println("Type:", reType.Name())
fmt.Println("Kind:", reType.Kind())
for i := 0; i < reType.NumField(); i++ {
field := reType.Field(i) //获取结构体的每一个字段
tag := field.Tag.Get(tagName)
fmt.Printf("%d. %v(%v):%v, TAG:'%v'\n",
i+1, field.Name, field.Type, reVal.Field(i), tag)
}
}
输出结果:
1. Name(string):AAA, TAG : -
2. Age(int):18, TAG : age,omitempty
3. Id(int):100, TAG : idx,string
4. Sex(string) :male, TAG : sex