Introducing “Go Pointers!”

Kent Rancourt
5 min readJan 4, 2019

Hello, and welcome to my Go Pointers series! This is something I’ve intended to do for a while now. It’s a new year, I’m fresh off two weeks of PTO, and feeling like there’s no time like the present.

Why I’m doing this

I think it’s important to examine my motivations. First, I won’t pull any punches here. I admittedly have a love/hate relationship with Go. On any given day working with Go, I’m certain to experience numerous highs and lows. In some moments, I’m awestruck by the elegant simplicity of the language or simply pleased as punch to make short work of a concurrency problem. I never fail to be amazed at the ease with which I can cross-compile code to target alternative operating systems and CPU architectures, in fact this is often my biggest motivation for using Go — that and the fact that it is undeniably the lingua franca of distributed computing. But then there are the things that drive me insane…

This is the part where most commentators would criticize Go for something like current lack of support for generics. And while, yes, I view that as a significant shortcoming of the language, I believe that, thematically speaking, there’s something broader that we can discuss in an episodic fashion that will help all of us to become better Gophers. In fact, I believe I will become a better Gopher by sharing what I know.

Essence vs Ceremony

Many years ago, I was as deeply entrenched in the Java/Spring ecosystem as I am the Go ecosystem now. On multiple occasions, I had the opportunity to hear Venkat Subramaniam speak about what he called “essence vs ceremony.” This was presented, at the time, in the context of Java vs Groovy, but the notion is more broadly applicable than that. I’m paraphrasing, but Venkat defined “essence” as the certain je ne sais quoi that makes a language useful. He defined “ceremony” as all the crufty stuff you manually (or with the help of tools) undertake as a matter of routine to work around the language’s deficiencies or simply because someone told you it was a best practice. Venkat posited that Java was high on “ceremony” while Groovy contained more “essence.”

I don’t want this post to devolve into a Java post, but I think it’s useful to explore a simple Java-based example.

In Java the visibility of a class’ attributes and member functions can be specified using keywords like public, private, and protected. If one wishes for some attribute of some class to be visible to other classes, it might be tempting to make the attribute public, but in many cases, this will break encapsulation. Perhaps, for instance, it is acceptable for the attribute's value to be read by other classes, but not mutated. By designating such an attribute as public, the desired read-only nature of the attribute isn't enforced, and the inner-workings of the class potentially begin to leak out into the rest of your code. This is no bueno. For as long as Java has been around, developers have worked around this by crafting public member functions called accessors and mutators (or more colloquially, "getters" and "setters") that control access to private attributes. This improves adherence to basic OO design principles. Want an attribute to be read-only? No problem. Only provide a "getter."

Bad:

Better:

Many exceptions to this exist of course — cases where “getters” or “setters” might perform more complex logic — but in general, what is problematic with even the better of the two approaches above is the shear frequency with which developers have to write such banal code. This is “ceremony.” Over time, IDEs have gotten smarter and more helpful and most can generate this sort of code on your behalf. But to what extent does that really address the problem? I’d argue not much. Despite the fact that you didn’t have to write the code manually, it still exists. It’s in source control somewhere, and someone will eventually see that code — and when they do, they very well may find such mundane code as this to be noise that distracts from much more important elements.

Groovy (which, compiles to Java bytecode and executes in a JVM just like Java) solves this particular problem by, in the absence of any access modifiers on an attribute, generating corresponding “getters” and “setters” for you at compile-time.

The same example in Groovy:

This example is logically identical to the better of our two Java examples, but comes without the “ceremony” tax. This is essence.

Oh, right… we were talking about Go…

Well, my friends. I’m sorry to inform you that while Go possesses much essence with regard to certain concerns — for instance, I feel its approach to concurrency qualifies — it nevertheless, with regard to many other concerns, is extremely high on ceremony — perhaps more so than any other language I have worked with. This is to say, the volume of best practices with which you must be acquainted in order to write (what I consider to be) good Go code is staggering.

Now this may not sound very complimentary, so please take this commentary with a grain of salt. Programming is very much an exercise in selecting the right tool for the job and I wouldn’t bother with this series if I didn’t think there were plenty of uses for which Go is well suited. Also keep in mind that Go is still a relatively young language and is almost certain to improve significantly over time.

In the meantime, whether we’re novices or experts, our Go chops only stand to be improved through a study of Go’s idiosyncrasies and some well-established methods of managing them. While I will occasionally stray from this theme, this is the essence of this series — mining a mountain of good Go practices one shovelful at a time.

What to expect

At this point in time, I’m not going to try to adhere to any specific schedule, but will endeavor to publish short and digestible posts as frequently as I am able. I’ll also make an effort to cover topics in a timely fashion as they crop up in my own work so that posts are well-informed by recent real-world experiences.

Stay tuned for the first (real) installment, dropping next week!

--

--

Kent Rancourt

Kent is a founding engineer at Akuity, working primarily with Kubernetes, Argo CD, and other open source projects.