我想递归地反映结构类型和值,但是失败了。 我不知道如何递归地传递子结构。

错误如下。

1
2
3
4
5
panic: reflect: NumField of non-struct type

goroutine 1 [running]:
reflect.(*rtype).NumField(0xc0b20, 0xc82000a360)
    /usr/local/go/src/reflect/type.go:660 +0x7b

我有两个结构PersonName

1
2
3
4
5
6
7
8
9
type Person struct {
    Fullname NameType
    Sex      string
}

type Name struct {
    Firstname string
    Lastname  string
}

我在main中定义Person,并使用递归函数显示该结构。

1
2
3
4
5
6
person := Person{
    Name{"James","Bound"},
   "Male",
}

display(&person)

display函数递归显示该结构。

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
func display(s interface{}) {
    reflectType := reflect.TypeOf(s).Elem()
    reflectValue := reflect.ValueOf(s).Elem()

    for i := 0; i < reflectType.NumField(); i++ {
        typeName := reflectType.Field(i).Name

        valueType := reflectValue.Field(i).Type()
        valueValue := reflectValue.Field(i).Interface()

        switch reflectValue.Field(i).Kind() {
        case reflect.String:
            fmt.Printf("%s : %s(%s)\
", typeName, valueValue, valueType)
        case reflect.Int32:
            fmt.Printf("%s : %i(%s)\
", typeName, valueValue, valueType)
        case reflect.Struct:
            fmt.Printf("%s : it is %s\
", typeName, valueType)
            display(&valueValue)
        }

    }
}
  • 检查此链接以了解解决方案:stackoverflow.com/questions/25047424/
  • 如果不在乎自己做,还是想看看别人是如何做的,请查看适用于Go的这款非常好的打印机github.com/davecgh/go-spew

display函数中,将valueValue声明为:

1
valueValue := reflectValue.Field(i).Interface()

因此,valueValue的类型为interface{}。 在for循环中,您可以递归调用display

1
display(&valueValue)

因此使用类型*interface{}的参数调用它。 在递归调用中,reflectType将表示interface{},而不是恰好存储在值中的类型。 由于只能在reflect.Type的表示结构上调用NumField,因此您会感到恐慌。

如果您想使用指向结构的指针来调用display,则可以使用以下方法:

1
2
v := valueValue := reflectValue.Field(i).Addr()
display(v.Interface())
  • @这是完美的权利。 我对reflect非常困惑,有reflect.TypeOf,reflect.ValueOf和这么多方法。 我需要更多时间来调查他们。 :)
  • 是否可以在"显示"功能中修改结构值? @詹姆斯·亨斯特里奇