【发布时间】:2021-05-27 10:27:17
【问题描述】:
这是我解析 xml 的代码。在函数结束时,我应该在值切片中包含结构的字段值。
func FindAttrs(attrs []Tag, errorChan chan<- error) {
var tableFields []reflect.StructField
for _, v := range attrs {
tableFields = append(tableFields, reflect.StructField{
Name: strings.Title(v.Name),
Type: reflect.TypeOf(""),
Tag: reflect.StructTag(fmt.Sprintf(`xml:"%v,attr"`, v.Name)),
Offset: 0,
PkgPath: "utility",
Index: nil,
Anonymous: false,
})
}
unmarshalStruct := reflect.Zero(reflect.StructOf(tableFields))
err := xml.Unmarshal(ReadBytes(errorChan), &unmarshalStruct)
HandleError(err, "Error parse config", false, errorChan)
values := make([]interface{}, unmarshalStruct.NumField())
for i := 0; i < unmarshalStruct.NumField(); i++ {
values[i] = unmarshalStruct.Field(0).Interface()
}
}
但是,它会因以下消息而恐慌:
reflect.Value.Interface: cannot return value obtained from unexported field or method
我称之为:
utility.FindAttrs([]utility.Tag{
{"name", reflect.String}, {"isUsed", reflect.String},
}, errorChan)
我的xml是<configuration name="mur" isUsed="mur"/>
【问题讨论】:
-
"cannot return value getting from unexported field" -- 意味着你要么必须导出字段,要么不做你想做的事做。
-
字段我是大写的,你可以在代码中看到。
-
我的错,我现在看到您正在使用 strings.Title。但是您的代码存在多个问题: 1. 删除字段的 PkgPath,用于未导出的字段。 2.你解组到
*reflect.Value而不是生成的结构类型,这不会像你期望的那样,即字段 Name 和 IsUsed 不会被 unmarshal 填充,因为它们不是反射的字段.Value 结构类型。 3. 你总是将第 0 个字段传递给循环中的第 i 个值。可能还有其他我没有发现的错误。 -
reflect.Zero返回一个reflect.Value,reflect.Value是基础值的通用表示,它不是实际值。所以&unmrshalStruct属于*reflect.Value类型,它不是属于你想要和需要的*struct { Name string, IsUsed string }类型。
标签: xml go struct reflection