一次搞定。
相关好文:
反射三部曲2·go反射实现结构体间赋值/不同结构体转换
我们构造如下结构体:
type Student struct {
Name string `json:"name" cn:"名字"` //
Age uint64 `json:"age" cn:"年龄"` //
Gender bool `json:"gender"` // true=男 false=女
level int `json:"level"` // 1=小 2=中
}
上代码:
func main() {
s := Student{
Name: "zhansam",
Age: 18,
Gender: false,
level: 2,
}
sType := reflect.TypeOf(s)
for i := 0; i < sType.NumField(); i++ {
fieldType := sType.Field(i)
fmt.Printf("属性名: %v, 字段是否可导出: %v, tag: %v, struct中第 %v 位\n", fieldType.Name, fieldType.IsExported(), fieldType.Tag, fieldType.Index)
fmt.Printf(" >>> tag值:%v, tag长度: %v\n", fieldType.Tag.Get("cn"), len(fieldType.Tag)) // 指定获取名为cn的tag值
}
}
speed running:
属性名: Name, 字段是否可导出: true, tag: json:"name" cn:"名字", struct中第 [0] 位
>>> tag值:名字, tag长度: 23
属性名: Age, 字段是否可导出: true, tag: json:"age" cn:"年龄", struct中第 [1] 位
>>> tag值:年龄, tag长度: 22
属性名: Gender, 字段是否可导出: true, tag: json:"gender", struct中第 [2] 位
>>> tag值:, tag长度: 13
属性名: level, 字段是否可导出: false, tag: json:"level", struct中第 [3] 位
>>> tag值:, tag长度: 12
如果是稍复杂一点的结构体呢,比如嵌套?
扩充一下Student结构:
type Student struct {
Name string `json:"name" cn:"名字"`
Age uint64 `json:"age" cn:"年龄"`
Gender bool `json:"gender"`
level int `json:"level"`
desc Desc `json:"desc" cn:"摘要"`
}
type Desc struct {
A string ` cn:"a"`
B int ` cn:"b"`
}
稍微包装一下,递归即可:
func getField(sType reflect.Type) {
for i := 0; i < sType.NumField(); i++ {
fieldType := sType.Field(i)
fmt.Printf("属性名: %v, 字段是否可导出: %v, tag: %v, struct中第 %v 位\n", fieldType.Name, fieldType.IsExported(), fieldType.Tag, fieldType.Index)
isStruct := false
if fieldType.Type.Kind() == reflect.Struct {
isStruct = true
fmt.Printf(" >>> 属性名: %v, isStruct: %v\n", fieldType.Name, isStruct)
getField(fieldType.Type) // 递归获取子结构体
}else{
fmt.Printf(" >>> tag值:%v, tag长度: %v, isStruct: %v\n", fieldType.Tag.Get("cn"), len(fieldType.Tag), isStruct)
}
}
}
func main() {
s := Student{
Name: "zhansam",
Age: 18,
Gender: false,
level: 2,
}
sType := reflect.TypeOf(s)
getField(sType)
}
speed running:
属性名: Name, 字段是否可导出: true, tag: json:"name" cn:"名字", struct中第 [0] 位
>>> tag值:名字, tag长度: 23, isStruct: false
属性名: Age, 字段是否可导出: true, tag: json:"age" cn:"年龄", struct中第 [1] 位
>>> tag值:年龄, tag长度: 22, isStruct: false
属性名: Gender, 字段是否可导出: true, tag: json:"gender", struct中第 [2] 位
>>> tag值:, tag长度: 13, isStruct: false
属性名: level, 字段是否可导出: false, tag: json:"level", struct中第 [3] 位
>>> tag值:, tag长度: 12, isStruct: false
属性名: desc, 字段是否可导出: false, tag: json:"desc" cn:"摘要", struct中第 [4] 位
>>> 属性名: desc, isStruct: true
属性名: A, 字段是否可导出: true, tag: cn:"a", struct中第 [0] 位
>>> tag值:a, tag长度: 7, isStruct: false
属性名: B, 字段是否可导出: true, tag: cn:"b", struct中第 [1] 位
>>> tag值:b, tag长度: 7, isStruct: false
由此,就可达到目的。
获取字段的值就更简单了:
valStu := reflect.ValueOf(s)
fmt.Println(valStu.Field(0)) // zhansam 根据位置获取
fmt.Println(valStu.FieldByName("Name")) // zhansam 根据字段名称获取
当然如果你的需要可能是判断更多类型,那么建议专门提供一个判断类型的函数,否则那么多if也是不优雅的。