Recently I’ve dug into another programming challenge with the Go programming language instead of Elixir. I wanted to tackle each year of advent of code in a different language, but I picked Go because of the promises it makes. Go purports to be a statically typed, compiled language with scripting language like syntax and faux dynamic typing. By being statically typed and compiled many common mistakes in programming can be caught before the program executes. However, the simplicity and succinctness of the language allow developers to work quickly and produce beautiful and maintainable code quickly. I’ve solved two problems now with Go and I’ve come away with some first impressions that I’d like to share now. The first and most important impression I came away with was Go’s compiler and CLI.
Command Line Interface
Go ships with a compiler and some command line tools to build, test, and install Go code. Building packages in Go is interesting because everything in a Go program must be packaged into one file. This means that all dependencies are linked at compile time and no other libraries can be “hot-loaded” once the program has finished building. On one hand, I think this is one of Go’s best features, but I can see where the limitations are in terms of deployment of Go binaries. However, the technology to get binary artifacts to computers quickly and efficiently has improved significantly over the years. In particular, CI and CD servers are able to push builds to remote PCs or servers with ease. Speaking of CI and CD, testing is a first class citizen in the Go programming language. You don’t need to install an implementation of xUnit and there’s no GoUnit equivalent. If you have Golang installed then you have everything you need to start writing tests. There’s not even any assertion libraries! You simply arrange, act, and write an if statement (basically an assertion) to see if your test passes. Finally, there’s the dependency management tooling. Dependencies in go are usually hosted on github and the go get command goes and fetches them for you.
Statically Linked Binaries
Go uses a very simple model of compilation. You take N number of source files and you process them in such a way that you produce 1 compiled binary out of it. This means that library changes cannot be deployed without an explicit recompilation of all the source code. This is, I think, a generally good approach, but for some businesses or software projects it may pose a problem. However, the benefits of being able to write once and compile for multiple different target operating systems is certainly a powerful feature.
The Go-pher operator
I’m a C# developer at heart and the Go-pher operator (so named because it looks like the Go gopher) is similar to C#’s var statement. The Go-pher operator is a quick and easy way to infer the type of the variable from the right hand side of an expression. See below for an example.
// this... int someNum1 = 0 // ...is the same as... someNum2 := 0
Not only does this make code more concise, but it also makes for a cute back story on the Go-pher’s design. Whether the origins are true or not are irrelevant because I choose to believe my superior version of events in Go’s development.
Go has a very fickle compiler, and it is rightly that way since everything outputs to a statically linked binary. Space is at a premium when you’re building a large binary file from hundreds-thousands of source files. Because of this, Go has very strict compilation requirements. Things that would be compilation warnings are now errors in Go. You cannot declare variables and not use them, you cannot check to see if a key in a map is empty by accessing it, and else has to start on the same line as the if statement’s ending curly brace. These are all minor nitpicks though because…
…Go is baby’s first systems language
This is the meat and potatoes of what Go is all about. It has always been about taking the raw programming talent at Google and pushing it with an easy to learn systems programming language. Go is essentially a wrapper for writing C programs in a nicer syntax. That’s really, really reductive, but I believe that’s what Rob Pike and Ken Thompson had in mind when they created it. Go feels like a sequel to their work at Bell Labs in the 70’s on Plan 9 and the B programming language. This idea of Go as an easy to learn primer on systems programming is further cemented by cgo. Cgo enables Go-C interop making the path to learning C much easier for those who want to do something manually in C which they can call from Go. It’s really a brilliant way to get programmers up to speed on languages that everyone should be using anyway.