Go语言学习笔记之反射用法详解

2020-01-28 12:41:26王旭


type user struct {
    name string
    age int
}
type manager struct {
    user
    title string
}
func main() {
    var m manager
    t := reflect.TypeOf(&m)
    if t.Kind() == reflect.Ptr {
        t = t.Elem()
    }
    for i := 0; i < t.NumField(); i++ {
        f := t.Field(i)
        fmt.Println(f.Name, f.Type, f.Offset)
        if f.Anonymous { // 输出匿名字段结构
            for x := 0; x < f.Type.NumField(); x++ {
                af := f.Type.Field(x)
                fmt.Println(" ", af.Name, af.Type)
            }
        }
    }
}

输出:


user main.user 0
 name string
 age int
title string 24

对于匿名字段,可用多级索引(按照定义顺序)直接访问。
type user struct {
    name string
    age  int
}
type manager struct {
    user
    title string
}
func main() {
    var m manager
    t := reflect.TypeOf(m)
    name, _ := t.FieldByName("name") // 按名称查找
    fmt.Println(name.Name, name.Type)
    age := t.FieldByIndex([]int{0, 1}) // 按多级索引查找
    fmt.Println(age.Name, age.Type)
}

输出:


name string
age int

FieldByName() 不支持多级名称,如有同名遮蔽,须通过匿名字段二次获取。

同样地,输出方法集时,一样区分 基类型 和 指针类型。
type A int
type B struct {
    A
}
func (A) av() {}
func (*A) ap() {}
func (B) bv() {}
func (*B) bp() {}
func main() {
    var b B
    t := reflect.TypeOf(&b)
    s := []reflect.Type{t, t.Elem()}
    for _, t2 := range s {
        fmt.Println(t2, ":")
        for i := 0; i < t2.NumMethod(); i++ {
            fmt.Println(" ", t2.Method(i))
        }