After running Go for two years in production at Iron.io, I wanted to share our experience/feelings about it. We were one of the first companies to use Go (golang) in production and we didn’t know what to expect in the long run, but so far, so great.



I talked a little about about this in a previous post about switching to Go from Ruby, but this will go into specific things that we love about the language, the things we learned along the way. In no specific order, here they are:





Performance

Memory

Concurrency

Reliability

Deployment

Talent

Performance

When we were first deciding on what language we were going to use, we did some research and created some mock tests for our use case, a message queue. I wrote a partial beanstalkd clone in Go that spoke the beanstalkd protocol so I could use existing clients to test it. Go performed very well, almost the same as the official C version (and it was surprisingly easy to write).



You can find benchmarks comparing Go to a bunch of other languages at the Computer Language Benchmarks Game site. The graph below compares it to Java (which would probably be the language we’d be using if Go didn’t exist):

That benchmark shows that Go is a bit faster in a few cases, but slower in the rest. Still, not too bad for a language that is only a few years old. I have no doubt it will catch up given some time. You can also see that the memory footprint is substantially better though.



Just for fun, c heck out the differences between Go and Ruby below, it’s insanely better in both performance and memory usage.





More Two years in, Go has never been our bottleneck, it has always been the database.





Memory Go doesn’t have a virtual machine or interpreter to load up, so it starts fast and small. IronMQ starts running in ~6444 KB of resident memory including loading configs, making connections, etc. After it’s been running for a while, it increases due to caching and what not. Right now, our production servers are running at ~400 MB (which I realize is somewhat irrelevant as this will depend on your application).



Two years in, we’ve never had a memory leak or problems related to memory.





Concurrency

Concurrency is a huge part of Go with some high level constructs that make it a breeze to use. I used Java for many, many years and got very comfortable with the java.util.concurrency package, which is a pretty nice set of concurrency tools, but it’s just not the same as Go in terms of simplicity or the underlying implementations. Go has goroutines for concurrent operations and channels for communicating between them. Goroutines are particularly interesting:

“Goroutines are part of making concurrency easy to use. The idea, which has been around for a while, is to multiplex independently executing functions—coroutines—onto a set of threads. When a coroutine blocks, such as by calling a blocking system call, the run-time automatically moves other coroutines on the same operating system thread to a different, runnable thread so they won’t be blocked. The programmer sees none of this, which is the point. The result, which we call goroutines, can be very cheap: unless they spend a lot of time in long-running system calls, they cost little more than the memory for the stack, which is just a few kilobytes. To make the stacks small, Go’s run-time uses segmented stacks. A newly minted goroutine is given a few kilobytes, which is almost always enough. When it isn’t, the run-time allocates (and frees) extension segments automatically. The overhead averages about three cheap instructions per function call. It is practical to create hundreds of thousands of goroutines in the same address space. If goroutines were just threads, system resources would run out at a much smaller number.” Source