Go is a fresh new programming language, that has come out of Google and is primarily targeted towards server development. It is developed by some very accomplished computer scientists, like Ken Thompson and Rob Pike. I recently launched a significant new product built with Go at work, and it has proved itself out very well in terms of developer productivity and performance. So much so that many other teams are also giving it a go (oh, how punny this language’s name is).
Think about it. How often do you come across a programming innovation that improves productivity and computational performance?
The Path to Go
Before I discuss Go, I would like to talk about how I was led to it. I started working in 2001 and handled multiple languages for the first couple of years while working on short web application development projects. My absolute favourite at that time was C++. In 2004, I started writing lots of code in PHP, non-Object Oriented. Though initially I hated it, especially for the fact that I couldn’t catch any errors without running the program first, I learned two important programming lessons for life:
- “Object Oriented” is just one way of programming, not the one way of programming. It’s not even the best, most of the time.
- Scalars (integers, characters, strings, floats, booleans), sequences (lists/arrays) and maps (key-value pairs) as built-ins are enough to support almost all data models.
While PHP was great for writing small scale applications quickly, it was hard to test, hard to debug (too much implicit type conversion) and SLOW. When I thought of taking a break from PHP, I jumped into Java in 2007. Java is perhaps the most depressing language I’ve ever programmed in. Too restrictive, too inexpressive (in other words verbose) and too “heavy”, with all the IDEs, frameworks, build environments etc. that needed to be set up before getting started. I also did not accept the JVM ideology. It’s too high a price for phantom portability.
In 2008, I started with Python. I had first played with it about five years earlier but this is when I got on to it full time. I loved Python. It was multi-paradigm, it was very expressive with brilliant stuff like list comprehensions, generators, decorators,
**kwargs, etc. Its biggest strength, though, was that all this expressiveness was so cohesively designed into the language that the WriteCode-Run-FixCode-Run… cycle frequently had 0 iterations. New code that I wrote worked as intended more often than in any other language.
When I started programming in Python, it appeared that Google had a lot of interest in the language. It’s creator, Guido van Rossum, was on their payroll. As days passed and progress on Unladen Swallow slowed, we heard of a new language from Google — Go. It would have been a bit easier to dismiss Go earlier on as an academic product, had it not been for the reputation of the people behind it, Rob and Ken, and the fact that it came from one of the most hard-core commercial software companies on earth. Back in 2009 when Go was announced, I did not understand much about why it was great, except that it had a lot of modern programming constructs and that it was fast.
Let’s hold this thought and go on a tangent for now.
In late 2010, when I moved to Zynga and got back from Python to PHP, I had the time to read up on some stuff. One of the books I read was this book, which offers a kind of gestational walk-through of programming language features using an academic programming language called Oz. Somewhere in its discussion, the book introduces a concept of “dataflow programming” and “declarative concurrency”. Now, you might want to follow the preceding link and briefly acquaint yourself with this concept because it is the centre-piece of Go’s language features.
When I learned about dataflow programming, I recalled how big a deal it was at Yahoo to be able to fetch data from multiple data sources in parallel and have resolution policies like fastest-source-wins, or wait-until-N-of-M-responses, etc., each with its own timeout handling and so on. The standard solution was a Java daemon with XML documents to describe the intended dataflow. It wasn’t pretty. I wished for this capability to exist in a language that, unlike Oz, wasn’t academic.
I did not realise at that time that Go was what I was looking for.
Some time early last year we started discussing about trying out other programming languages — compiled languages, to be more specific — to get better-than-PHP levels of performance. That’s when I again started exploring Go and discovered that it had gathered a lot more backing at Google and gone GA, version 1.0. In the middle of last year, we started bouncing ideas about a new project which required handling concurrency. The PHP shared-nothing architecture wasn’t going to work. I thought it was the right time to take Go for a spin.
Working with Go
I got a real feel for programming with Go while working on the project’s prototype. Here’s what I observed:
- Compiler assistance: It felt really good to get back to a compiled language. The compiler not only checks for code that can theoretically result in a runnable program, but also disallows things that can lead to problems later on. This isn’t a unique property of Go, but it’s there and that’s good.
- Standardized formatting: A standard tool to enforce formatting rules that is not subject to change based on the team members’ or leader’s opinions is a welcome feature for lowering the “not my code” mental barrier.
- Small language: Go is a very compact language. It’s not bursting at the seams with features. It’s a lot like C in that regard, minus the “undefined behaviour” proliferation. That makes it easy to learn and start programming with.
- Batteries included: The Go standard library has all the bits and pieces needed to write a server program, whether it be a webserver, raw socket server or anything else that requires access to OS built-ins.
- Easy to jump in: Time to get started with Go is pretty short. Much less than languages that require elaborate frameworks and IDEs to get set up.
- Fast time to “done”: Productivity with Go is really high. There is so much of common server programming components built into the language or its standard library that you can write fairly complex servers in very little time. Less code also means faster time to correct program behaviour.
- Multi-core, High performance: The runtime is surprisingly fast and stable. It feels spectacular, for someone used to writing servers in Python, etc. Unlike Python and Node.js, the Go runtime is capable of spawning multiple OS threads and having them execute in parallel.
Go in Production
Some of the features of Go don’t seem to be significant until you deploy it to production. The things that I really love about Go in this regard are:
- Single Binary: Go produces statically linked binaries that are self sufficient and would execute on any system that they’re built for. This is especially great for cloud based deployments because your deployment node does not need anything beyond a bare-bones OS image. Compare this to the elaborate dependency setup that is required for most other application environments and the benefits become obvious.
- Cross Compilation: Earlier I mentioned about the JVM being a bad trade-off for phantom portability. In practice, non-trivial Java programs also require porting for different systems. Coupled with dependency management on target systems, portability of Java programs becomes tougher. The nice thing about Go is that I can have my entire build environment for development and testing on my Ubuntu or OS X system and compile for RHEL in production. All I need to do is copy over the cross-compiled binary and I’m done with portability!
- Built-in Profiling: With just a few lines of code, you can have an HTTP end-point that will give you live profiling capability for CPU, memory, goroutines, OS threads, lock contention etc. You can use the go toolchain to hit that URL and profile the application on-demand while it’s executing and handling live traffic. That’s just brilliant!
- Shareable Code: One of the biggest impediments to code sharing is the size of a project, or the amount of code it has. Even if people have access to some codebase, it’s not always easy for them to dive in and understand the code. Since it takes far fewer lines of code to do the same thing in Go compared to C, C++ or Java, the code is more accessible to others and therefore more shareable. The limited language spec also means that it’s less likely that someone might run into obscure constructs or “advanced features” that some people know of and most don’t.
To conclude, I have found Go to be the best server programming language I have tried so far. It combines the elegance of Python with the performance of C and C++. Even if it is only 90% as easy as Python and 90% as fast as C or C++, it still works out to be a winning combination. Its benefits are not just restricted to productivity and performance, though. Go applications are easier to develop and deploy across heterogenous systems and virtualised environments. It’s also easier to share and collaborate on Go programs, thanks to a single formatting standard, small language spec and concise code.