Some of the most popular things on this blog have been diaries I’ve written as I explore my way through a new technology or hobby. I’m picking up the Go Programming Language, whose HQ is (significantly) at golang.org and which I’m going to refer to as “Golang” for reasons which should become obvious. Whatever you thing of Golang, it’s apparently got some momentum and some seriously smart people are working on and in it; so this may actually be of service to the community.

At this point, I should tip my hat to Mark Pilgrim, who taught me that a really good time to write about something is while you’re still discovering it, before you’re looking at it from the inside.

Big Gripes · My leading gripes with Golang right now probably aren’t the biggest problems with the language; rather, the biggest obstacles to learning it.

First, the name. “Go” has too many meanings and is among the world’s lousiest Google search disambiguators. After a few painful instances of searching for things like “go array literals” and “go repl” I got into the habit of sticking with Golang; and so will this diary.

The second big gripe is that Golang has neither an IDE nor a REPL. I don’t think, in 2013, that I should insult my readers’ intelligence by explaining why these are good things for a programming language to have.

I have sort of a REPL workaround, a little Golang program called c.go in which I can try coding idioms and type go run c.go ; Golang’s compiler is very fast and its diagnostics are really good. But it’s not a real REPL; I can’t build up exploratory state.

Illustrated Love Letter · So here’s a little code fragment that I’ll use to illustrate a few things about Golang that seem nice to me. Well, and some minor gripes too.

type Vector []float64 func (v Vector) MeanAndSignum() (mean float64, signum []int) { total := 0.0 signum = make([]int, len(v)) for i, value := range v { total += value switch { case value < 0.0: signum[i] = -1 case value == 0.0: signum[i] = 0 case value > 0.0: signum[i] = 1 } } mean = total / float64(len(v)) return }

Let’s step through this line-by-line.

type Vector []float64

A Golang type is not a class, it’s more like a C typedef . Which is easy to understand, and probably one of the reasons why Golang is fast.

func (v Vector) MeanAndSignum() (mean float64, signum []int) {

There’s a lot of stuff to unpack here:

Golang isn’t object-oriented. So while nothing is an object, anything can be the target of a method. The leading (v Vector) means that if you’ve got a Vector named foo , you can write foo.MeanAndSignum() to call this function. And that inside the body of the function, you can refer to the receiver of the function as v ; quite reminiscent of self in Python.

The fact that MeanAndSignum is capitalized means that it’s exported; visible outside whatever package you’ve defined it in.

The (mean float64, signum []int) is really clever. It says that this method returns two values (yes!) and simultaneously defines names for them that you can use inside the function. Then when you return , whatever the current values are is what gets returned. I like this a lot. This also illustrates Golang’s idiosyncratic declaration rhythm (name then type) and even more idiosyncratic array-declaration syntax.

total := 0.0

The := says I’m declaring a variable, and please infer its type from the right-hand-side of the statement. I could also have said var total float64 = 0 , but this is super-readable.

signum = make([]int, len(v))

I don’t have to declare signum because I did that up in the function declaration. make is a built-in that allocates an empty whatever; once again, I admit I haven’t entirely warmed up to the array syntax. I’m also unconvinced that the distinction between := and = is essential; feels like unnecessary ceremony.

for i, value := range v {

Now this is really sweet. The for/range construct gives you both the array index (in i ), and the value (in value ). Of course, there’s syntax for ignoring either. Very handy.

total += value

Nice C-flavored code (there’s even ++) but look, Ma, no semicolons!

switch { case value < 0.0: signum[i] = -1 case value == 0.0: signum[i] = 0 case value > 0.0: signum[i] = 1 }

Isn’t that a nice compact switch idiom? Definitely C-done-right. Of course, in some other languages switches are expressions that return values, sigh.

mean = total / float64(len(v))

Yeah, it’s statically typed, so you have casting. I’m not sure why it was a good idea to invent a new syntax, but this one seems OK. I’m also not sure why, since you have type inference, you can’t also have type auto-conversion, even Java would do the right thing without a cast. But no biggie.

return

See, because you named the return values in the declaration, you don’t need to mention them explicitly here. But if you want you can have traditional return statements including the values.

Nits & Whining · Maybe I’ll come to realize eventually that these aren’t problems, but they’re irritating me at the moment.

Golang will not let you compile if there’s an import or declared variable that’s unused. OK, I understand that Cleanliness Is Next To Godliness, but this is seriously slowing me down; probably a third of my attempts to run my damn program fail because I’ve forgotten to remove debugging apparatus, or I’ve sketched in a variable but not used it yet. How about a compiler switch or something?

There doesn’t seem to be a way to declare a constant array, what in a Java class I’d call final static String[] COLS = {"Red", "Blue"};

In fact, I still find array declarations and literals egregiously weird, for example [...] . I’m really hoping it starts to feel natural, because I’ve rarely managed to type in an array declaration right first time so far.

Responsive! · I filed a bug on June 6th, and it was fixed on the 12th. Gotta love that.