返回

Go REFLECT 库 | 02 - 反射的类型 Type 继续讲解

前端

三、反射获取结构体

在通过指针的 反射类型对象 获得了指针指向的对象之后,我们就可以获取指针指向的具体对象类型,这一类型的特征与属性都被记录在 反射类型对象 中。反射类型对象 与具体类型都有自己的方法,因而 反射类型对象 也可以通过方法获取具体对象属性值、调用具体对象方法等。
反射类型对象 的方法包括 NumField()Field()FieldByIndex(),这些方法可以用于获取反射类型对象中的结构体信息(字段信息)和字段的具体值。
NumField() 方法用于获取反射类型对象中的结构体字段数量,Field()FieldByIndex() 方法用于获取反射类型对象中的字段。字段是一个 StructField 类型的值,它包含了字段名称、类型、偏移量、索引等信息。通过 StructField 中的索引,可以通过 FieldByIndex() 方法获取字段的具体值。

// 定义一个结构体
type User struct {
    Name string
    Age  int
    Sex  string
}

func main() {
    u := User{Name: "tom", Age: 18, Sex: "male"}
    // 创建一个反射类型对象
    t := reflect.TypeOf(u)
    // 获取结构体的字段数量
    num := t.NumField()
    fmt.Println("结构体字段数量:", num)
    // 获取结构体的字段信息
    for i := 0; i < num; i++ {
        field := t.Field(i)
        fmt.Println("字段名称:", field.Name)
        fmt.Println("字段类型:", field.Type)
        fmt.Println("字段偏移量:", field.Offset)
        fmt.Println("字段索引:", field.Index)
    }
    // 获取结构体的字段值
    v := reflect.ValueOf(u)
    for i := 0; i < num; i++ {
        field := t.Field(i)
        value := v.FieldByIndex(field.Index)
        fmt.Println("字段名称:", field.Name)
        fmt.Println("字段类型:", field.Type)
        fmt.Println("字段值:", value)
    }
}

输出结果如下:

结构体字段数量: 3
字段名称: Name
字段类型: string
字段偏移量: 0
字段索引: [0]
字段名称: Age
字段类型: int
字段偏移量: 8
字段索引: [1]
字段名称: Sex
字段类型: string
字段偏移量: 16
字段索引: [2]
字段名称: Name
字段类型: string
字段值: tom
字段名称: Age
字段类型: int
字段值: 18
字段名称: Sex
字段类型: string
字段值: male

通过以上代码,我们可以获取结构体中的字段信息和字段值。需要注意的是,Field()FieldByIndex() 方法只能获取结构体的公开字段,如果需要获取私有字段,则需要通过 Unsafe 包中的方法来实现。