During my Introduction to Go class last Thursday at YAPC::NA::2015, one of the class attendees, David Adler, asked a question along the lines of “why use Go?” That’s a good question, so here is my answer.
Let’s start by first talking about why we use Perl (or Ruby, Python, PHP, JS, etc.). Why use a dynamic language? There are a lot of reasons, but the basic answer is that these languages make it easy to get a system up and running quickly. They are easy to write, include a lot of useful features (regexes, IO, core libraries, etc.), they eliminate large classes of bugs, and generally get out of your way when coding. These languages perform well enough for many tasks, and so the fact that they are not as fast or memory efficient as they could be is not a concern.
But of course, sometimes speed and memory usage are a concern. I suspect that many dynamic language users reach for C or C++ when they need to optimize something. Here’s why …
In Perl, a basic scalar value is represented by a C struct called an SV
(see perlguts for
gory details). A quick check with Devel::Size tells me that a scalar containing the number 1
uses 24 bytes of memory on my system. A 3 byte string uses 42 bytes of memory. In a language like C,
those values can use as little as 1 and 3 bytes respectively.
This isn’t an issue when dealing with hundreds or thousands of such values. The Perl program uses 24 times as many bytes for each integer, but when you’re just dealing with 5,000 integers, this only adds up to 120kib vs 5kib. However, once you start dealing with millions of values (or more), this can become a problem. The program has to allocate memory, usually doing many small allocations. What’s worse is that operations on these values are slower. Integer math in Perl goes through many more steps than in C. Again, for a small number of operations this isn’t a problem, but for millions or billions of operations, the cost becomes significant.
Of course, C and C++ have their own issues, including the difficulty of managing memory, the potential security holes, the segfaults, the double frees, and lots of other fun.
Enter Go. Go gives you a statically compiled language with the potential for carefully managing memory usage while also protecting you from the memory management bugs (and security holes) that C and C++ allow for.
So why use Go? I think that Go is a compelling option for any task that you’d do in C or C++ instead of a dynamic language. Go is fast to run, relatively easy to write, and comes with a pretty good set of core libraries. It gives you many of the niceties of a dynamic language while still offering memory efficiency and high speed.
As a huge plus, Go compiles down to static binaries that are incredibly easy to deploy. This will make your sysadmins or devops folks quite happy.
Of course, Go doesn’t replace C or C++ for all tasks. It’s a garbage collected language, which means that if you need complete control over memory allocation and freeing, it won’t cut it. I don’t expect to see an OS in Go any time soon.
Also, the language itself is missing out on some features that might be appealing for some systems. The example I often use is a database server. I would much rather try to write such a thing in a language like Rust than Go. Rust seems to combine low level optimizability with some nice high level features like generics and traits. If I were writing something complex like a database server (or a browser) I think I’d want those features. But Go is great for things like web application servers, command line tools, and anything else that isn’t a huge complicated system.
(And yes, I know there are people writing database servers in Go. I’m just saying that Go probably wouldn’t be my first choice for such a tool.)