英文:
Couldn't unmarshal xml to a dynamically created struct using reflection in Golang
问题
这是我的解析XML的代码。在函数的末尾,我应该在values切片中拥有结构体字段的值。
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: 无法返回从未导出的字段或方法获取的值
我这样调用它:
utility.FindAttrs([]utility.Tag{
{"name", reflect.String}, {"isUsed", reflect.String},
}, errorChan)
我的XML是<configuration name="mur" isUsed="mur"/>
。
英文:
This is my code for parsing xml. At the end of the function, I should have values of fields of a struct in the values slice.
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()
}
}
But, it panics with the following message:
reflect.Value.Interface: cannot return value obtained from unexported field or method
I call it with:
utility.FindAttrs([]utility.Tag{
{"name", reflect.String}, {"isUsed", reflect.String},
}, errorChan)
And my xml is <configuration name="mur" isUsed="mur"/>
答案1
得分: 0
需要将指向结构体的指针传递给Unmarshal函数,而不是传递结构体本身。可以通过Interface()
函数获取指针的值。
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)),
})
}
rv := reflect.New(reflect.StructOf(tableFields)) // 初始化一个指向结构体的指针
v := rv.Interface() // 获取实际值
err := xml.Unmarshal([]byte(`<configuration name="foo" isUsed="bar"/>`), v)
if err != nil {
panic(err)
}
rv = rv.Elem() // 解引用指针
values := make([]interface{}, rv.NumField())
for i := 0; i < rv.NumField(); i++ {
values[i] = rv.Field(i).Interface()
}
英文:
Need to make a pointer to struct instead of a value and pass pointer's value, which can by retrieved Interface()
function, to Unmarshal instead of it itself.
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)),
})
}
rv := reflect.New(reflect.StructOf(tableFields)) // initialize a pointer to the struct
v := rv.Interface() // get the actual value
err := xml.Unmarshal([]byte(`<configuration name="foo" isUsed="bar"/>`), v)
if err != nil {
panic(err)
}
rv = rv.Elem() // dereference the pointer
values := make([]interface{}, rv.NumField())
for i := 0; i < rv.NumField(); i++ {
values[i] = rv.Field(i).Interface()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论