This month, I decided to give the Go programming language a try. After two weeks reading and hacking, I open sourced my very first program written in Go: msw, a tool that helps us build a Modern Science Weekly issue each week.

A Tour of Go

I am not going to write yet another “how I learned to stop worrying and love Go”, but I must admit I have been really impressed by this language so far. The language is not new, which speeds the learning curve a bit as there are countless articles, tutorials, and code snippets. Writing about Go in 2016 is not trending I guess, but I had a PhD to complete beforehand… Anyway, here is a summary of my Go experience.

The official documentation put aside, Go by Example has been great to quickly approach fundamental concepts for the first time. This video on Go concurrency patterns is awesome to understand some design decisions, and that one on Go tooling is also worth watching (more on this in a moment). Mitchell’s Advanced Testing with Go talk (slides) is useful to learn a few more tips too!

Tooling: ♥ ♥ ♥

Having everything bundled in the Go dev environment by default is very nice. It makes the development experience very smooth. One advantage of having a rather small yet complete toolbox included by default is that integration with IDEs and editors can be pushed farther: the supported tools are the official tools, and there is no pointless discussions about choosing the right tools among tons of similar ones. The vim-go plugin is a great example, but I heard vscode-go was huge too! Because I truly love this feature, the screencast below shows the code coverage integration in vim:

vim-go and code coverage
feedback

Testing: Simple yet Efficient

Talking about testing, Go recommends the use of table-driven tests (also known as data providers in PHPUnit for instance). This is a feature I often miss in many other languages and I am glad to see it as a best practice! Below is an example extracted from our msw tool:

func TestNewInvalidArgs(t *testing.T) {
	ui := new(cli.MockUi)
	cmd := &command.NewCommand{UI: ui}
	cases := []struct {
		args     []string
		expected string
	}{
		{nil, ""},
		{[]string{"abc"}, "Invalid issue number"},
		{[]string{"-date=1234-56-78", "123"}, "Error, parsing time"},
		{[]string{"-date=1234", "123"}, "Error, parsing time"},
		{[]string{"-directory=invalid", "123"}, "no such file or directory"},
	}

	for _, c := range cases {
		code := cmd.Run(c.args)
		if code != 1 {
			t.Fatalf("Expected code = 1, got: %d (args = %v)", code, c.args)
		}
		if !strings.Contains(ui.ErrorWriter.String(), c.expected) {
			t.Fatalf(
				"Expected UI to contain '%s', got: %s (args = %v)",
				c.expected,
				ui.ErrorWriter.String(),
				c.args,
			)
		}

		ui.ErrorWriter.Reset()
	}
}

Performance: Built-in.

Go is a language used to write concurrent applications that perform well, hence a set of bundled performance tools like pprof, and benchmark functions. Such functions are very similar to test functions except that they are only executed by the go test command when its -bench flag is provided:

$ go test -bench . [-cpuprofile=cpu.prof]

Combined to Uber’s awesome go-torch (and the -cpuprofile flag), you can quickly obtain an interactive SVG flame graph helping you understand why your app is not fast enough:

Documentation: I’m Lovin’ It (Again)

I am not a huge fan of over-commented code but I like interfaces explaining their roles/responsibilities, and I am not against a one-line comment about a tricky part of internal code either. What is great with Go is that documentation matters. All exported code (that is visible by other pieces of code) have to be commented. The godoc (bundled) tool is useful to produce documentation as HTML or plain text, e.g., the msw documentation, automatically built from sources by godoc.org.

You may think that it looks like Javadoc, or whatever-doc else, but there is no need to learn a sort of new language for writing comments, it is simply plain old text describing things. Once again, developer experience is improved.

Final Thoughts

I have written code in different languages over the last six years, and Go looks like everything I loved in other languages put into a single one. No need to find/install many tools to get ready, the syntax is readable (especially when you have some PHP background), the standard library is huge, and there a plenty of libraries available. I should also mention cross compilation, which I tried with mitchellh/gox.

By the way, the numerous Hashicorp open source projects are a goldmine!

–William