[英]golang - reflection on embedded structs
给定一个像这样的结构:
type B struct {
X string
Y string
}
type D struct {
B
Z string
}
我想反思 D 并进入 X、Y、Z 领域。
直观地说,在尝试解决方案之前,我假设我能够遍历结构 D 并使用反射(X、Y、Z)获取所有字段,而不必处理 B。
但是正如您所看到的,我只看到使用反射的嵌入式结构 B 而不是它的字段。
http://play.golang.org/p/qZQD5GdTA8
有没有办法让 B 在反射到 D 时完全透明?
我为什么要这个?
对一个公共结构(此处示例中的 B)进行成像,该结构通过使用嵌入在多个其他结构中使用。 使用反射,尝试将 D 复制到不同包中的另一个类似结构中。 用于复制的目标结构将具有平面布局的所有属性(没有嵌入)。 因此,从源到目标存在不匹配(嵌入与无嵌入),但所有平铺的属性都是相同的。 我不想为每个结构创建自定义解决方案。
您期望的“透明度”只是语法糖,与数据表示无关。 如果您想拥有一个扁平化数据结构的函数,则必须自己编写。
例如(在玩):
func DeepFields(iface interface{}) []reflect.Value {
fields := make([]reflect.Value, 0)
ifv := reflect.ValueOf(iface)
ift := reflect.TypeOf(iface)
for i := 0; i < ift.NumField(); i++ {
v := ifv.Field(i)
switch v.Kind() {
case reflect.Struct:
fields = append(fields, DeepFields(v.Interface())...)
default:
fields = append(fields, v)
}
}
return fields
}
使用以下代码收集所有提升的字段名称作为映射m
键:
func collectFieldNames(t reflect.Type, m map[string]struct{}) {
// Return if not struct or pointer to struct.
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
if t.Kind() != reflect.Struct {
return
}
// Iterate through fields collecting names in map.
for i := 0; i < t.NumField(); i++ {
sf := t.Field(i)
m[sf.Name] = struct{}{}
// Recurse into anonymous fields.
if sf.Anonymous {
collectFieldNames(sf.Type, m)
}
}
}
像这样使用它:
m := make(map[string]struct{})
collectFieldNames(reflect.TypeOf((*D)(nil)), m)
for name := range m {
fmt.Println(name)
}
该程序按照问题的要求打印 X、Y 和 Z,但也打印 B,因为 B 也是字段名称。
此答案中的此功能可以改进:
encoding/json/encode.go 中的typeField
函数处理这两个问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.