解组可选的float64字段在Go上返回错误

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 (
    "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
", 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?

I believe you have discovered a bug, you should report it on the issue tracker, 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 <grade/> tag completely and use xml:"grade,omitempty" in your struct.

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:"Person"`
    Grade   Grade    `xml:"grade"`
    Name    string   `xml:"name"`
}

This parses the <grade> 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.