The Go Programming Language

I am always on the look out for new programming languages. It is my vain hope that some day a language will be developed that will distil all the lessons we have learned about programming language design so far and will unlock new highs of productivity and creativity. In my opinion, the ‘Go’ programming language is a very good attempt at doing this for system engineering.

The Go Gopher by Renée French
The Go Gopher by Renée French, see here for more about the logo.

Background

Go is just 3 years old and only recently achieved its first stable milestone release, version 1.0.0, in March 2012. It has been designed and built internally at Google by Rob Pike and Ken Thompson (both known for the Plan9 operating system, UTF-8 and Unix), Robert Griesemer (who worked on Strongtalk and the Hotspot JVM), and others. Their remit was to design a language that could scale to cope with the huge number of interconnected systems, users, engineers, and lines of code that Google needs to deal with day to day.

So what does it look like then?

It is a statically typed, garbage collected language that sits at the level somewhere between C/C++ and Java/C#, and compiles down to platform native code.

Although it has a C-like syntax, it also includes high-level features like built-in dictionary/map support similar to scripting languages like JavaScript or Python, and function closures like JavaScript.

Here’s an example, taken from Rob Pike’s “Go Concurrency Patterns” talk, that demonstrates several important features:

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    // A function returning a channel
    c := boring("boring!")

    for i := 0; i < 5; i++ {
        // Read a string from the channel and print it
        fmt.Printf("You say: %q\n", <-c)
    }

    fmt.Println("You're boring; I'm leaving.")
}

// A generator function that returns a receive-only channel of strings.
func boring(msg string) <-chan string {
    // Create the channel of strings
    c := make(chan string)

    // Define an anonymous function and run it as a goroutine
    go func() {
        for i := 0; ; i++ {
            // Send a message to the channel
            c <- fmt.Sprintf("%s %d", msg, i)
            time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
        }
    }()

    // Return the channel to the caller
    return c
}

I’ll leave it to Rob to explain what’s going on here in detail. Admittedly, this may be a little challenging to understand if you are not already familiar with the basics of the language. For a quick step-by-step introduction take the tour.

Probably the most important feature is its support for parallelism and concurrency. For this, Go’s designers refer to ideas from a 1978 paper (really has it take us the length of my entire lifetime to get here?) by Tony Hoare called “Communicating Sequential Processes”. These are realised in Go by goroutines, which are concurrent processes that communicate with each other by sending messages over channels. The idea is, by coordinating through message passing, rather than shared memory, it enables lock-free programming.

What I like about it so far

I have only been investigating it for a few weeks, and haven’t built anything significant with it yet. However, there are already a number of features that appeal to me. I had intended to keep this list small, but to hell with it, there are a lot of things I like about it already :-)  here we go:

Oh, it also has a cute mascot called the ‘Gopher’ [see the image above] :-)

Toolchain and workflow

What is also excellent about Go is that the tool-chain has not been left an after-thought.

It comes bundled with more than just a compiler, so there is no need to mess around with makefiles!! :)  This makes it very easy to get up and running.

The main way of building Go source code is by using the go front-end command-line tool. It has a simple Git/Subversion inspired interface, with sub-commands for building, installing, testing, formatting, and various other tasks.

It also has a run sub-command that builds and runs in one step. Impressively, because the compiler is fast enough, this means that Go can be used almost as if it is a scripting language. A simple idea really, but a nice touch that makes it so easy to code up small experiments and small tasks. I have often created shell scripts to do the same in C when trying to hack out a small idea quickly.

As far as I can tell at the moment, there are two main schemes for source organisation:

Interestingly, it appears there is no middle ground here: if you take the first scheme and try to organise some of your code into packages in sub-directories, the compiler just cannot find the nested sources. Granted, there may be a way around this but I need to dig deeper (please tell me if I’m wrong). Anyway, for more on this topic see: here.

What types of tasks is it good for?

At the moment it appears to be targeted at writing network and system services. But, I guess this may expand in time. Here’s a big list of projects written in Go.

SoundCloud are using it to write back-end systems.

Further reading

Here are some other interesting sources of information: