无法在Golang中使用反射将XML解组为动态创建的结构体。

huangapple go评论74阅读模式
英文:

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&lt;- error) {
	var tableFields []reflect.StructField
	for _, v := range attrs {
		tableFields = append(tableFields, reflect.StructField{
			Name:      strings.Title(v.Name),
			Type:      reflect.TypeOf(&quot;&quot;),
			Tag:       reflect.StructTag(fmt.Sprintf(`xml:&quot;%v,attr&quot;`, v.Name)),
            Offset:    0,
            PkgPath:   &quot;utility&quot;,
			Index:     nil,
			Anonymous: false,
		})
	}
	unmarshalStruct := reflect.Zero(reflect.StructOf(tableFields))
	err := xml.Unmarshal(ReadBytes(errorChan), &amp;unmarshalStruct)
	HandleError(err, &quot;Error parse config&quot;, false, errorChan)
	values := make([]interface{}, unmarshalStruct.NumField())
	for i := 0; i &lt; 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{
		{&quot;name&quot;, reflect.String}, {&quot;isUsed&quot;, reflect.String},
	}, errorChan)

And my xml is &lt;configuration name=&quot;mur&quot; isUsed=&quot;mur&quot;/&gt;

答案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(&quot;&quot;),
			Tag:  reflect.StructTag(fmt.Sprintf(`xml:&quot;%v,attr&quot;`, 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(`&lt;configuration name=&quot;foo&quot; isUsed=&quot;bar&quot;/&gt;`), v)
	if err != nil {
		panic(err)
	}

	rv = rv.Elem() // dereference the pointer
	values := make([]interface{}, rv.NumField())
	for i := 0; i &lt; rv.NumField(); i++ {
		values[i] = rv.Field(i).Interface()
	}

huangapple
  • 本文由 发表于 2021年5月27日 18:27:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/67720273.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定