我正在尝试使用反射构建一个例程,该例程将在传入的任意结构中列出所有字段的名称,种类和类型。这是到目前为止的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
type StatusVal int
type Foo struct {
    Name string
    Age  int
}
type Bar struct {
    Status StatusVal
    FSlice []Foo
}

func ListFields(a interface{}) {
    v := reflect.ValueOf(a).Elem()
    for j := 0; j < v.NumField(); j++ {
        f := v.Field(j)
        n := v.Type().Field(j).Name
        t := f.Type().Name()
        fmt.Printf("Name: %s  Kind: %s  Type: %s
", n, f.Kind(), t)
    }
}

func main() {
    var x Bar
    ListFields(&x)
}

输出如下:

1
2
Name: Status  Kind: int  Type: StatusVal
Name: FSlice  Kind: slice  Type:

当字段是切片时,类型为空白。 我尝试了几种方法来获取切片的数据类型,但是所有尝试都导致了恐慌……通常是这样:

1
reflect: call of reflect.Value.Elem on slice Value

需要对此代码进行哪些更改,以便所有字段(包括切片)的类型都将在输出中列出?

这是游乐场链接:https://play.golang.org/p/zpfrYkwvlZ


在像[]Foo这样的类型文字中给出的切片类型是未命名的类型,因此Type.Name()返回空字符串""

使用Type.String()代替:

1
t := f.Type().String()

然后输出(在Go Playground上尝试):

1
2
Name: Status  Kind: int  Type: main.StatusVal
Name: FSlice  Kind: slice  Type: []main.Foo

请参阅相关问题以了解有关类型及其名称的更多信息:使用reflect识别非内置类型

  • 美丽! 谢谢icza!