在Go语言中,解组可选的float64字段会返回错误。

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

Unmarshalling optional float64 field returns error on Go

问题

我的翻译如下:

我的应用程序使用的外部API有时会在float64字段中返回空值。当发生这种情况时,我无法解析文档的其余部分。

以下是Go Playground中的示例代码:

package main

import (
	"encoding/xml"
	"fmt"
)

func main() {

	type Result struct {
		XMLName xml.Name `xml:"Person"`
		Grade   float64  `xml:"grade"`
		Name    string   `xml:"name"`
	}

	data := `
		<Person>
			<grade/>
			<name>Jack</name>
		</Person>
	`
	var v Result
	err := xml.Unmarshal([]byte(data), &v)
	if err != nil {
		fmt.Printf("error: %v", err)
		return
	}
	fmt.Printf("name: %s\n", v.Name)

}

如果我将第12行的float64更改为string,它将正常工作。有什么办法可以解决这个问题吗?我应该将每个字段都定义为string并手动进行转换吗?

英文:

The external API that my application is using, sometimes returns no values for one of the float64 fields. When that happens, I cannot unmarshal the rest of the document.

Here is the sample code in Go playground:

http://play.golang.org/p/Twv8b6KCtw

package main

import (
	&quot;encoding/xml&quot;
	&quot;fmt&quot;
)

func main() {

	type Result struct {
		XMLName xml.Name `xml:&quot;Person&quot;`
		Grade   float64  `xml:&quot;grade&quot;`
		Name    string   `xml:&quot;name&quot;`
	}

	data := `
		&lt;Person&gt;
			&lt;grade/&gt;
			&lt;name&gt;Jack&lt;/name&gt;
		&lt;/Person&gt;
	`
	var v Result
	err := xml.Unmarshal([]byte(data), &amp;v)
	if err != nil {
		fmt.Printf(&quot;error: %v&quot;, err)
		return
	}
	fmt.Printf(&quot;name: %s\n&quot;, v.Name)

}

If I change float64 in line 12 to string, it will work. Any idea how I can get a workaround for this? Should I just define every field as string and do the conversion manually?

答案1

得分: 4

我相信你发现了一个错误,你应该在问题跟踪器上报告它,我已经提交了一个错误报告问题 8333

现在针对当前的问题,你有两个选项:

  1. 使用string类型,根据需要自己将其转换为浮点数。
  2. 完全删除<grade/>标签,并在你的结构体中使用xml:"grade,omitempty"
英文:

I believe you have discovered a bug, <s>you should report it on the issue tracker</s>, I submitted a bug report issue 8333.

Now for the current problem, you have 2 options:

  1. Use string type they do your own conversation to float on demand.
  2. Remove the &lt;grade/&gt; tag completely and use xml:&quot;grade,omitempty&quot; in your struct.

答案2

得分: 4

为了补充OneOfOne的解决方案,你还可以定义自己的UnmarshalXML方法。

示例(在play中查看):

type Grade float64

func (g *Grade) UnmarshalXML(d *xml.Decoder, s xml.StartElement) error {
    for tok, err := d.Token(); err != io.EOF; tok, err = d.Token() {
        if chrdata, ok := tok.(xml.CharData); ok {
            f, err := strconv.ParseFloat(string(chrdata), 64)
            if err != nil {
                return err
            }
            *(*float64)(g) = f
        }
    }
    return nil
}

type Result struct {
    XMLName xml.Name `xml:"Person"`
    Grade   Grade    `xml:"grade"`
    Name    string   `xml:"name"`
}

这段代码通过在<grade>标签中搜索CharData标记并将其解析为浮点数来解析,当没有要解析的值时,将等级设置为0.0

英文:

To add to OneOfOne's solutions, you can also define your own UnmarshalXML method.

Example (On play):

type Grade float64

func (g *Grade) UnmarshalXML(d *xml.Decoder, s xml.StartElement) error {
	for tok, err := d.Token(); err != io.EOF; tok, err = d.Token() {
		if chrdata, ok := tok.(xml.CharData); ok {
			f, err := strconv.ParseFloat(string(chrdata), 64)
			if err != nil {
				return err
			}
			*(*float64)(g) = f
		}
	}
	return nil
}

type Result struct {
	XMLName xml.Name `xml:&quot;Person&quot;`
	Grade   Grade    `xml:&quot;grade&quot;`
	Name    string   `xml:&quot;name&quot;`
}

This parses the &lt;grade&gt; tag by searching for CharData tokens in between and parsing them as float, leaving the grade at 0.0 when there is no value to be parsed.

huangapple
  • 本文由 发表于 2014年7月7日 10:04:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/24602155.html
匿名

发表评论

匿名网友

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

确定