反射三部曲1·go反射获取结构体字段名、tag、值等

一次搞定。

 相关好文:

反射三部曲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也是不优雅的。

你可能感兴趣的:(go实战大满贯,golang,go,服务器)