Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

encoding/xml: unmarshaling empty xml val into non-zero struct has inconsistent behavior #19855

Closed
s-mang opened this issue Apr 5, 2017 · 2 comments
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@s-mang
Copy link
Contributor

s-mang commented Apr 5, 2017

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go version devel +f8b0231639 Mon Mar 20 20:54:19 2017 +0000 linux/amd64

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/usr/local/google/home/shadams/go"
GORACE=""
GOROOT="/usr/local/google/home/shadams/dev/go"
GOTOOLDIR="/usr/local/google/home/shadams/dev/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build400923614=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"

What did you do?

If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on play.golang.org is best.

package main

import (
	"encoding/xml"
	"fmt"
)

type Parent struct {
	I     int
	Child struct{ I int }
}

const emptyXML = `
<Parent>
    <I></I>
    <Child></Child>
</Parent>
`

func main() {
	p := &Parent{I: 1, Child: struct{ I int }{2}}
	if err := xml.Unmarshal([]byte(emptyXML), p); err != nil {
		panic(err)
	}

	fmt.Printf("int (%v) vs struct (%v)\n", p.I, p.Child)
}

What did you expect to see?

int (0) vs struct ({0})

What did you see instead?

int (0) vs struct ({2})

An empty xml val always results in a zero-valued destination, regardless of any pre-populated values, except if type is struct, ptr to struct, slice of struct, etc.

This was existing behavior before https://go-review.googlesource.com/c/38386/. Not sure if it makes sense to change at all, but wanted to document the inconsistency.

cc @rsc @bradfitz @ianlancetaylor

@bradfitz bradfitz added this to the Go1.9 milestone Apr 5, 2017
@bradfitz bradfitz added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Apr 5, 2017
@rsc
Copy link
Contributor

rsc commented Apr 6, 2017

That's correct, documented behavior:

<Parent><Child><I>1</I></Child></Parent> would overwrite Parent.Child.I
<Parent><Child></Child></Parent> does not - it doesn't mention I.
<Parent></Parent> does not either - it doesn't even mention Child.

I would rephrase your rule from:

An empty xml val always results in a zero-valued destination, regardless of any pre-populated values, except if type is struct, ptr to struct, slice of struct, etc.

to

An empty xml val unmarshaled into a basic type is treated as a zero value.

That is, the general case is "walk further into the data structure" and it continues to work as before. It's the "treat empty string as zero" that is new, except that it's not. It's just a rule for interpreting data. This is split out in the 'go doc xml.Unmarshal' docs.

Note also:

<Parent><Child><I>2</I></Child></Parent> writes 2 to Parent.Child.I.
<Parent><I>2</I></Parent> writes 2 to Parent.I.
<Parent><Child>2</Child></Parent> does nothing (there's nowhere to put the 2).
<Parent>2</Parent> does nothing (there's nowhere to put the 2).

This is the basic difference in the example in the report too: if the field is named, then a value is fetched for it and stored there. If not, it's not.

@s-mang
Copy link
Contributor Author

s-mang commented Apr 7, 2017

Ah, I see. So it's not an inconsistency.
Thanks for the explanation. I'll leave it to you, @rsc, to close the issue as you see fit.

@rsc rsc closed this as completed Apr 7, 2017
@golang golang locked and limited conversation to collaborators Apr 7, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

4 participants