Should Go's struct field tags support some whitespace?

1,848 views
Skip to first unread message

zack.m...@gmail.com

unread,
Jan 28, 2016, 9:14:15 PM1/28/16
to golang-nuts
It was suggested to me that, since the Go language spec does not mention supporting whitespace in tags, I should create a discussion here.

Here's a link to a gist containing my findings, in glorious markdown: https://gist.github.com/zsck/7a1d880ca25c953d1f06

Note that I originally posted this as an issue, so the tone isn't really slanted towards being a discussion starter.  Please ignore that.

The short story is this:
When you define a struct in Go, you can give fields tags to specify things like what key to look for or encode a field as when decoding from/encoding to JSON respectively.
If you use a space between the colon (:) character and start of the string containing the key/field name, Go will ignore the tag.
My case is that this little bit of whitespace shouldn't lead to behavior like this without at least generating a warning at compile time.  I think it would be preferable if at least the most common whitespace characters could allowed.

Ian Lance Taylor

unread,
Jan 28, 2016, 9:16:52 PM1/28/16
to zack.m...@gmail.com, golang-nuts
For the record, the current syntax of struct tags is documented at
https://golang.org/pkg/reflect/#StructTag . I think you are
suggesting that optional whitespace be permitted after the colon and
before the quoted value.

Ian

zack.m...@gmail.com

unread,
Jan 28, 2016, 9:24:13 PM1/28/16
to golang-nuts, zack.m...@gmail.com
Yes, that is what I mean.
Thanks for the added clarity!

roger peppe

unread,
Jan 29, 2016, 3:39:36 AM1/29/16
to zack.m...@gmail.com, golang-nuts
Your example is misleading you, I think. You suggest that there's
an asymmetry between json marshaling and unmarshaling
but actually struct tags are parsed in exactly the same way
in both cases. The reason your unmarshal example works
is that the JSON unmarshaler works case-insensitively.
If you changed it so that the tag name was not just a lower-cased
version of the field name, you'd find that unmarshaling would
not work either.

For me, I don't really see that it's worth adding the white space parsing
there. If in doubt, run go vet, which will tell you that your tags
are invalid:

tst.go:9: struct field tag `json: "name"` not compatible with
reflect.StructTag.Get: bad syntax for struct tag value

cheers,
rog.
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Tyler Compton

unread,
Jan 29, 2016, 5:22:59 PM1/29/16
to golang-nuts, zack.m...@gmail.com
I think struct tags should allow for whitespace, too, unless it somehow introduces ambiguities or something similar. Most people I know put a space between keys and values when writing map literals and things like that, so it's only natural that they would do that for struct tags, too, unless they were aware of this rule. I would expect that the work to accomplish this would be minimal and the value would, in my opinion, be high because it removes a "gotcha" of the language.

Dave Cheney

unread,
Jan 29, 2016, 6:47:41 PM1/29/16
to golang-nuts
But where would it end? A single space begats multiple, and the call for tab, and then \n so you could wrap them.

And of course, these new forms would not be understood by previous versions of the reflect library.

zack.m...@gmail.com

unread,
Jan 30, 2016, 12:51:22 PM1/30/16
to golang-nuts, zack.m...@gmail.com
Lots of great discussion in here.

I'm feeling a fair bit better about this spacing concern now that I know `go vet` can catch it, and I understand that my example was a bit contrived.
Thing is, I designed my example to be a bit contrived. I actually ran into the problem in the context of a web server I was building and wasn't able to catch the problem
with my unit tests.  I can see how I was confused by the fact that decoding was working because of the case-insensitive fallback mechanism, but it really
did create a lot of trouble for me when I was encoding values in my HTTP response and decoding them in my unit test.  In between, I didn't realize what was
actually happening.  It wasn't until I did some manual testing to look at responses that I realized things weren't what I expected. By that point, I was very confused
because of the apparent asymmetry between encoding and decoding.

I think it'd be reasonable to just allow spaces in the tag.  Any sufficiently well designed parser (and I'm setting a low bar here) shouldn't have any trouble recognizing
any number of spaces.  I think it'd be ideal if we could treat tags the same way as multi-line strings (since they're contained in back-ticks) but I understand that may
be overzealous.

Florin Patan

unread,
Jan 30, 2016, 8:58:37 PM1/30/16
to golang-nuts
There are tools which detect this issue (go vet, any editor that integrates with it or Go plugin for IntelliJ). Granted, this still happens to me rarely but that's why I have go vet (and golint) to the test pipeline / pre-commit hook.

I'm usually thinking at least twice when using more than a couple of tags for the same field. That means reflection which for me is a bad thing. Or maybe it means that the structure has too many responsibilities and that's an even bigger problem.

> I think it'd be ideal if we could treat tags the same way as multi-line strings

I would suggest coming up with a real scenario where lacking this would be a deal breaker.

To end this on a fun note, why stop there? String consts should be usable as tags, no?

Andrew Gerrand

unread,
Jan 31, 2016, 6:11:02 PM1/31/16
to zack.m...@gmail.com, golang-nuts

On 31 January 2016 at 04:50, <zack.m...@gmail.com> wrote:
I think it'd be reasonable to just allow spaces in the tag.

To add a contrary opinion: I think it's good that tags can only be written with specific formatting. We have gofmt so that all Go code looks the same, but the contents of string literals (eg, struct tags) are outside gofmt's purview. By making tag parsing strict, everyone's struct tags must look the same. That's a benefit to the ecosystem at large.

Andrew

Tyler Compton

unread,
Feb 1, 2016, 2:27:01 PM2/1/16
to golang-nuts, zack.m...@gmail.com
I think you've highlighted on the issue here. Yes, code consistency is good, and that's what this should be about. The Go community should be encouraging people to not put spaces between struct tag keys and values because of convention, not because it's absolutely necessary to do so for fear of the tag silently failing. This is not a good way to enforce convention.

In Go, unused variables are a compiler error because they could /potentially/ be a sign of a bug. However, benign-looking struct tags that in fact don't work aren't given the same treatment, even though a struct tag with a space is almost /definitely/ the sign of a bug. It's understandable, since they are strings and only "kind of" a part of the language, but if we can't give the user a valuable error message to a very simple mistake like this one, it should probably just not be considered a mistake in the first place.

Andrew Gerrand

unread,
Feb 1, 2016, 3:40:33 PM2/1/16
to Tyler Compton, golang-nuts, Zsck
Well, we do give them a valuable error message with 'go vet'.
A better solution IMO is to more widely encourage the use of vet.

--

Tyler Compton

unread,
Feb 1, 2016, 3:52:07 PM2/1/16
to golang-nuts, xav...@gmail.com, zack.m...@gmail.com
Alright, fair enough. I can get behind that.

Mike Orr

unread,
Feb 1, 2016, 4:22:47 PM2/1/16
to Tyler Compton, golang-nuts, zack.m...@gmail.com
Because of the following factors in combination:
- Go's alphabetic case rules (which I like btw) make struct tags virtually mandatory for the very common case of any type that will be serialized to json,
- The whitespace rule in tags is unexpected from other parts of the language,
- The symptoms of violating the rule are far downstream and somewhat obscure,

this clearly merits an error imho. If we call this lint, we're on a path that would basically turn vet into a very poor version of compiler warnings, the absence of which is one of my favorite things about Go.

$0.02,
Mike

Reply all
Reply to author
Forward
0 new messages