400 days of Go

It’s been 418 days since my first Github commit of Go code. In that time I’ve written a Syslog-to-Kafka producer, a Raft-based distributed SQLite database, a near real-time log search system, and become a core developer of InfluxDB.

So if there is one word to summarize Go, it’s productive.

I haven’t had the same burst in productivity since I first started building web services in Python, so what have been the key reasons?

No IDE required

I’ve written much of my Go code using nothing but vim. Sometimes Sublime, but often just vim. I once tried to write Java code using vim, and the runaway proliferation of source files, of AbstractSingletonProxyFactoryBeans, quickly made an IDE required. Not so with Go, and this is important.

Fast build times

Compile and link a C++ program. Do it 10s of times a day. It adds up to minutes, sometimes hours. But not with Go. The entire InfluxDB system compiles, with Go 1.4, in 3 seconds on my machine. An entire distributed time-series database compiled to native code in 3 seconds. This has done wonders for the productivity of the InfluxDB development team.

Standard library

The standard library is a joy to work with. Many parts of it show me that the Go team really did have systems software in mind when designing the language. Little things like making it easy to set read-and-write timeouts on sockets, or gather server statistics, have made it so much faster to produce robust and reliable code.

Key data structures built-in

Maps are a ubiquitous data structure in programming — I’d guess that 10-20% of all Go code I work with involves maps. That the Go team decided to make them a built-in for a statically-typed language was an incredibly important decision, that has made the language so much more powerful.

Dynamic arrays — Slices in Go — are also critical to Go’s productivity. Along with the functions append and range, coding with these key data structures is a breeze.

By building both in, it has resulted in a standard and systematic way for Go programmers to deal with these data structures. This has become a force-multiplier within teams of Go developers and the wider Go community.

go fmt

Sometimes you don’t realise how much time you are spending doing something until you are not doing it any longer. Source code layout conventions are one of those things. Debating bracket placement, character spacing, noisy diffs due to whitespace changes — all banished to a time before Go. go fmt is an inspired tool, and it is a tribute to the Go team that the choices made by the tool have been so readily accepted by the Go community.

Single binary

Even though this is widely acknowledged when discussing Go, I believe it remains an under-appreciated attribute of Go, something that will become even more important as time passes. Network and storage are cheap, but the deployment, configuration, and management of modern computer systems is not. Anyone who has spent time in Technical Operations — as I have — knows the pain of dependency hell, JDK upgrades, or installing Perl-bindings. The single-binary approach is, and will remain, a significant productivity boost.

Test framework

The test framework is excellent. And perhaps as important, using just the standard library’s test framework has proved to me that using only the standard library (when humanly possible) is the right approach to writing Go code. There are many, many test frameworks for Go, and the temptation to use a third party library is strong, but sticking with one framework keeps the code consistent, which helps productivity enormously.

Performance analysis

The performance analysis tools — CPU profiling and memory profiling — have been key to development at InfluxDB. After all, it’s only with databases that O(n) comes alive.  It’s been fascinating analysing — and fixing — the database Go code I’ve written using the CPU profiler.

Tell me how you really feel

So is there anything not so bright-and-shiny?

Garbage collection

Strangely, some key parts of Go don’t feel like they have made a huge difference. Sure garbage collection is nice, but I never had too much trouble writing leak-free C and C++, not with technologies like Valgrind and Boost Smart Pointers. Now I may underestimate the work GC is doing for me — quite possibly — but if I had to track the memory myself, and still write Go code, I don’t think I’d really mind.

Boilerplate

I certainly find myself writing chunks of boilerplate during Go development. This can make code maintenance more difficult. With a language like C++ there is a drive to abstract everything to avoid this issue, and to make heavy use of features such as templates (generics). But anyone who has written a reasonably-sized C++ program knows that this drive is relentless and that’s the problem — it’s very easy for abstraction to go too far.

Within our industry there is now a drive to return to simplicity. Go’s easy acceptance of writing a little boilerplate to make source code navigation less cumbersome , and its comprehension easier, is actually refreshing.

GOPATH

GOPATH is weird. Once you get the hang of it, it’s fine, but early in my Go programming days it caused plenty of confusion. It feels like a bolt-on, and I’ve learned to use a separate GOPATH for every project. It doesn’t feel right, an often I wonder how it made it into the Go system.

The Go Way

gopherGo feels like a pedantic language, but that suits most programmers. It certainly suits me.

Syslog clients, distributed databases, and search systems. And all without a JVM or V8 engine in sight. After 300 days with node.js, the succeeding 400 days with Go have been so much better.

20 thoughts on “400 days of Go”

      1. Using one GOPATH does not hinder separation.

        GOPATH
        ../bin
        ../pkg
        ../src
        …./project1
        …./project2
        …./project3

        and if you plan on distributing…
        ../src
        …./github.com
        ……/yourusername
        ……../yourpackagename(project4)

        One GOPATH. All the seperation you’ll ever need. Adding a new GOPATH for every single project seems ridiculous to me.

        1. Regularly backing up one’s own program sources is difficult when many “go gotten” sources are mixed into the src directory with them, resulting in bloated backup files. A separate src directory for each project is easier for doing zips of sources.

    1. I do this as well. Despite the fact that you don’t need an IDE, using one can certainly increase productivity. Using a separate GOPATH per project reduces the number of files my IDE needs to index as well as the number of choices for me to wade through when it suggests packages to import.

  1. Thanks for all the feedback.

    I know a distinct GOPATH is not required, but I find it useful to have such a distinction between workspaces. When it comes to my InfluxDB development — a well-known open-source project — I find it particularly important to maintain a workspace that is clean of any other dependencies, and this is the way I do it. The last thing I want to do is commit or rely on code that is not an explicit dependency specified by InfluxDB (obviously this is unlikely to happen in practise). It suits me to keep my work siloed in this manner.

    1. If you have your git repo directly in $GOROOT or $GOROOT/src you’re “doing it wrong” (or at least against what’s prescribed by tools like ‘go get’ and general best practice).

      You should be namespacing your code.

      Having your git repo and source for example in ‘$GOROOT/src/github.com/githubuser/githubproject’ instead of directly in src will make your code much more reusable by other projects that shouldn’t have to re-vendor your code just to use it.

      1. Thanks Jesse.

        Yes, I follow the practise as you outlined it for my recent personal projects, and as we do at InfluxDB . See our CONTRIBUTING file, to see what we (and I) do.

        And I think you mean GOPATH, no?

  2. I also have the impression to be productive in Go but like you said there’s a lot of boilerplate to write, more than the other languages I use.

    About gofmt one thing that makes me mad is that you can’t import a package you’re not using, seriously I want to keep log imported in case I’d like to print something for testing stuff without having to delete the line and rewrite it every damn time. There should be an option for that.

    I like Go and all, but seriously, I don’t understand that Java rant about AbstractSingletonProxyFactoryBeans, you’re talking (and linking to) about a class that no one uses directly on a daily basis, in a version of Spring that is 8 years old. It has recently become a breeze to write apps and services with Java and Spring, there’s no need to bash them in here 😉

    1. I completely agree with Alex. Every article that bashes Java links to the same Spring glass. With Java8, Spring 4.x, and many of today’s modern Java tooling, every other language seems underwhelming.

  3. Interesting read, though not getting the IDE part, still not getting it after reading the linked code smell blog post.

    My main benefit of an IDE (for Scala) is:

    – Syntax check, unused variable check etc. to prevent compiles for ‘syntax checking’/ not getting out of the zone

    – Jump to a class, IDE is clever enough to find the class based on fragements

    – Jump to a method from the code

    – Auto import

    – Debugger

    I wonder why with Go this is not needed. Faster compilation makes syntax checks/unused vars check in IDE not necessary? Less files? Does Go import everything? Larger import scopes? How do you find the implementation of a method? How is debugging working in Go?

    Is the compiler integrated into vim? The debugger? Thx.

  4. Have been using GO for about the same amount of time and I agree “productive” is the optimal word. I have found an editor (vim / atom / sublime text … ) with integrated lint and fmt to be a huge time saver and nice addition when programming with GO. My team has moved away from python in favor of GO for a huge part of our software with little or no productivity loss, and significant performance gain. Good Summary

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">