Saturday, August 13, 2011

Go peeve

Take the following Go program.

package main

import "fmt"
import "json"

type Foo struct {
    Wham int
    Bam  string
}

type Bar struct {
    gee  int
    whiz string
}

func main() {

    var f Foo
    f.Wham = 42
    f.Bam = "hello world"
    msg, _ := json.Marshal(f)
    fmt.Println(string(msg))

    var b Bar
    b.gee = 42
    b.whiz = "hello world"
    msg, _ = json.Marshal(b)
    fmt.Println(string(msg))
}

Before knowing any better, I would have guessed the program produces two lines of JSON, with each line populated by two fields. But what the program actually produces is as follows.

{"Wham":42,"Bam":"hello world"}
{}

In other words, the first object is converted to JSON, but the second one isn't. The reason why has to do with what, in my opinion, is a design flaw in Go.

Go, like some other modern languages, tries to prevent style-and-format jihad from breaking out between developers by forcing them to use a specific style. Relevant to this case is that Go determines whether a member is public or private depending on the capitalization of the member's name. Lower case members are private; uppercase members are public. No argument.

Until now, during my tentative forays into Go, I've perceived this as a harmless quirk of the language. But when using the standard json package, it's not harmless.

The json.Marshal() function, which converts arbitrary Go objects into JSON-formatted strings, works only on public members. All lowercase members are ignored. In other words, you can't use Go and JSON and lowercase names—at least, not easily.

Normally, I don't care about style requirements imposed by languages. I adopt a when in Rome attitude and squash opinions about how code ought to be formatted, instead formatting my code the same as the language's standard library. But by using JSON it's nearly certain I'm interfacing between two or more languages—e.g., Go and Javascript—and in this case Go's quirks are imparted onto those other languages.

In Javascript I use camel-back notation for member names, thus matching the convention of the language. But I can't use camel-back for members of a JSON-derived object if that object is ever accessed in Go. Fortunately, Javascript is flexible and doesn't care how I name members, so I can make things work by using uppercase. But still this highlights one way in which imposing style on developers is problematic.


By the way, I'm aware that today is Saturday, just as I was aware that I last posted on Wednesday and that this week's blogging schedule differs from my regular Monday-Thursday. I assure you the oddity has nothing at all to do with how I've lost track of what day of the week it is because of my unemployment. Rather, I wish to post three times this week. That is all. It shan't happen again!

5 comments:

Unknown said...

MVC code-first does some stuff like this as well. It's ironic that those design decisions are (I think) intended to make the language/framework easier to learn. Instead, they leave experienced developers scratching their heads trying to figure out schizophrenic behavior.

Anonymous said...

You lost me at hello. -- BW

Craig Brandenburg said...

Chad— Go's styling issue detracts from what is otherwise a language that innovates in all the right ways. Keep in mind Go isn't a marketed language. It's not a platform, it's not locking anyone in to anything, and it's not making anyone any money—not Google, not directly anyway.

In the case of Go, I think the styling issue isn't meant as anything; it's just a preference of the language designers. As it happens, it's a strong enough preference for them to wish to mandate it on everyone who uses their language.

Anonymous Bobby— Sometimes Just Enough Craig is too much.

Anonymous said...

This bothered me too, but apparently it's possible to get around it...

Craig Brandenburg said...

Anonymous— Thanks for pointing that out. Though I've known about json tag values for a while, your comment makes my post a little less wrong.