On Monday, work announced that we would be adopting Google Go as a third official internal language. Most software houses have two official languages: a highly demanding systems language with strong performance and memory guarantees, and an easy-to-write scripting languages with mediocre performance and few memory guarantees, so a third language was a bit unusual. Work's language pair was C++ and Python, a highly conventional and conservative choice1.
My commute takes me past a bookstore so on the walk home Monday I bought Introducing Go and read it on the train, and the next morning read the rest. It's a tiny book. We're at the end of a project at work so I had spare time. I chose a little toy project.
I've been trying learn Rust, and I have a little server project called Monologued that I've been hacking on since early December. I haven't gotten it working. I already had some major components working, and I decided to try at write Monologued in Go.
To be fair, I had work's support at learning Go, and I don't have it for learning Rust, so I could use office time to write the Go version, whereas my Rust time has to compete with my writing time, which is about 35 minutes twice a day, in a crowded transit train.
Here's what I discovered:
Go is a good language for writing middling-performance servers. It's concurrency model is brilliant and easy to use, and the garbage collection makes it easy to forget about memory management. The error handling is old-school but clear and fairly concise. The compiler is clearly optimized for the cognitive support of modern, "smart" IDEs, but I was just using Emacs and still managed to write the server in a short period of time.
But...
I hated it.
Have you ever watched one of those music videos where very talented musicians take children's musical instruments and do something utterly and mind-bogglingly amazing with them? There is something quite astonishing about watching someone take all the skill they've spent thousands of hours mastering only to wring lovely music out of toy pianos, plastic recorders, kindergarten bongos, and little wooden xylophones. It's only when you step back for a moment and realize that if they sound that amazing on toys, they must be even more amazing when playing on instruments meant for adult hands.
That's how I feel writing in Go. I didn't learn anything writing in Go. It's a language with guard rails, a language of Lego pieces. It's "batteries included" library is so complete it has all the parts needed to build web servers instantly. Go is such a simple language that if you're coming from Python the syntax enforcement will drive you crazy for a while but then, like Python's whitespace, you'll get used to it, and you'll like the lack of the global interpreter lock. If you like Python 3, Go's Unicode management is lousy and you won't enjoy it, but it's workable. If you're coming from C, the tuple return type and memory management will make you very happy, and otherwise you'll be completely in your element. All the headaches of POSIX-style networking are hidden behind a pretty API.
No one will ever write great software in Go.
Look at the great programs of the last 25 years. Look at the LAMP stack: Linux, Apache, MySQL, PHP— all written in C. The alternatives: FreeBSD, Microsoft Windows; Nginx or Lightspeed; Maria, Postgres, or Mongo; Perl, Python, Ruby— all written in C or C++. The MS Suite of Word, Excel, Access, Powerpoint, OneNote, Publisher— all written in C++. Almost all the great software of the last 25 years was written in C or C++.
This is not to say that I think C and C++ are perfect languages. They're not; their closeness to the operating system and the hardware, the features that give them their immense power, also make them notoriously hard to master and exceptionally difficult to get right. D attempts to correct C++'s issues but hasn't gotten much traction. But Go gets something right: We need something faster and smarter than Python without the nightmares of C and C++.
Rust takes a different tack: it learns from C and C++'s mistakes without hiding from your awareness the underlying issues of talking to an OS. Its rigid memory model takes a lot of effort to master, but it's completely worth it. When you master Rust, you'll have mastery over the bare metal, the machine itself. Go is the dull knife of programming.
I fully acknowledge that Go is a very good language for what it does. It meets a very important business need: it makes developers productive, and it lets them get product out the door in very short periods of time, and it's stupid simple. It makes shareholders happy. It takes all the lessons learned since Pascal and reifies them into a usable language; it takes all the lessons learned since Lisp and ignores them completely.
Working in Go does not suck. The problem is that if you're not working in something that sucks, you are not growing. You're stuck. Rob Pike, the co-inventor of Go (and Unix, and UTF-8, and a ton of other things) once said
The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt. – Rob Pike
And that's my problem with Go. It doesn't encourage growth. A developer working in Go and only Go will help his business's bottom line, and the shareholders will be happy, but he will always be a mediocre programmer which is why mediocre coders are so fond of Go. That quote above is on the wall in my office, and I try to live by it. You should too.
The alternative is that you will not be Rob Pike, a guy who's still making changes in the industry even though he's ten years older than I am. You'll be writing the same thing for twenty years and then, when you're forty, you'll know nothing else... and then what will you do?
1In almost every job I've head, the pair has always been C or C++, Python or Perl. The oldest job I ever took had just COBOL; the oddest pair was Java and Perl in 2010, but that can be explained by the fact that it was a publishing toolchain and there's a ton of Perl for managing LaTeX. Isilon's choice of Python was a bit idiosyncratic; in 2000 chosing Python was considered radical, but 18 years later Python has completely overwhelmed Perl as the scripting language of choice, so the choice now seems prophetic. I'm pleased that I'm the one who made that choice.