我对golang反映行为感到困惑。
所以基本上我有一个名为src
的切片,其类型为[]interface{}
。我想得到每个元素的实际类型。这就是我所做的:
src := []interface{}{"noval", 0, nil}
srcType := reflect.ValueOf(src)
for i := 0; i < srcType.Len(); i++ {
each := srcType.Index(i)
if each.Interface() == nil {
fmt.Println("value", each.Interface(), "is nil")
} else {
switch each.Kind() {
case reflect.String:
fmt.Println("value", each.Interface(), "is string")
case reflect.Int, reflect.Int16:
fmt.Println("value", each.Interface(), "is int")
default:
fmt.Println("value", each.Interface(), "is ?")
}
}
}
输出:
value noval is ?
value 0 is ?
value <nil> is nil
我不明白为什么{@ 1}}未检测到元素"noval"
的类型,而是从string
调用default
。
此外,switch
值应标识为0
,但reflect.Int
会再次调用。
请有人赐教,请提前谢谢。
答案 0 :(得分:4)
src
是一个元素类型为interface{}
的切片。因此,您获得的每个元素都是静态类型interface{}
,因此他们的#34;类型&#34;将是reflect.Interface
。添加新的reflect.Interface
案例将揭示:
case reflect.Interface:
fmt.Println("value", each.Interface(), "is interface")
输出将是(在Go Playground上尝试):
value noval is interface
value 0 is interface
value <nil> is nil
如果你想要&#34;包裹&#34;界面中的元素,使用Value.Elem()
:
} else if each.Kind() == reflect.Interface {
switch each.Elem().Kind() {
case reflect.String:
fmt.Println("value", each.Interface(), "is string")
case reflect.Int, reflect.Int16:
fmt.Println("value", each.Interface(), "is int")
default:
fmt.Println("value", each.Interface(), "is ?")
}
}
然后输出(在Go Playground上尝试):
value noval is string
value 0 is int
value <nil> is nil
另请注意,您已经&#34;切换&#34;超过种类的值,而不是实际的类型。这意味着多种类型的值可能会在特定情况下结束,如下所示:
type mystr string
src := []interface{}{"noval", 0, nil, mystr("my")}
srcType := reflect.ValueOf(src)
// ...
这将是(在Go Playground上尝试):
value noval is string
value 0 is int
value <nil> is nil
value my is string
值mystr("my")
被检测为string
,因为它是string
&#34; kind&#34; ,但其类型不是{ {1}}但是string
。这可能是也可能不是你想要的。如果您想区分mystr
和string
类型的值,那么您应该&#34;切换&#34;在这个例子的实际类型中:
mystr
然后输出(在Go Playground上尝试):
} else if each.Kind() == reflect.Interface {
switch each.Elem().Type() {
case reflect.TypeOf(""):
fmt.Println("value", each.Interface(), "is string")
case reflect.TypeOf(0):
fmt.Println("value", each.Interface(), "is int")
case reflect.TypeOf(mystr("")):
fmt.Println("value", each.Interface(), "is mystr")
default:
fmt.Println("value", each.Interface(), "is ?")
}
}
如您所见,value noval is string
value 0 is int
value <nil> is nil
value my is mystr
被检测为"nova"
类型的值,而string
被正确检测为mystr("my")
类型的值。
另请注意,对于您尝试做的事情,您不需要反思,只需使用type switch:
mystr
输出(在Go Playground上尝试):
src := []interface{}{"noval", 0, nil}
for _, v := range src {
switch v.(type) {
case string:
fmt.Println("value", v, "is string")
case int:
fmt.Println("value", v, "is int")
case nil:
fmt.Println("value", v, "is nil")
default:
fmt.Println("value", v, "is ?")
}
}