In Defense of the Hosted Language: Why Golang isn't the Catch-all, End-all

When I first heard about Golang, I sincerely thought the JVM was obsolete. Its day was past in my head. After all, when I wrote in Go, I felt like I was writing in Java or Python, because it was garbage collected. At the same time, since it was cross-compilable, it was as portable as Java, but I didn't need to install a run time first. As a DevOps engineer, I really saw the benefit. I still do.

But as I have learned, it has its drawbacks. For example, say I want to write a GUI application. With the JVM, I can do all of it in pure Java. (Not that you would want to do this, but bear with me.) But I can't do it in Golang without using CGo. Why? Well, this is because you need to interact with native code to write a GUI because assembly is the language in which computer graphics speak (ish -- I know I'm glossing over details) and that is most easily interfaced with using a native language like C, C++ or Rust. With Java, I can bake that native code into the JVM, then call that native code using Java. With golang, I'm out of luck, precisely because golang is compiled and needs to bring all of its dependencies with it. With the JVM or similar runtimes, you can spend lots of time making sure a runtime compiles correctly on a particular system, then make that runtime widely available. After that, programming for it becomes really easy. I believe this is why Java's JNI is discussed much less (and, me guessing again, is probably used less) than golang's CGo.

Once you use CGo, you lose golang's benefits over java in the first place. In all honesty, I really like having exceptions and generics.

If I'm a DevOps engineer building a cross-platform desktop application, I really like the idea of using Go -- until we talk about CGo. At that point, I'm choosing between packaging a JVM in with my application (think Windows), or I'm compiling on every target OS for all of my libraries. The former is a lot of up-front work, but after that becomes easy; the latter is easier, but with lots of corner cases that will pay dividends in annoying bugs over time.

Even as such an engineer deploying an app to the Kubernetes cluster, CGo means that I have to really make sure I compile for the right version of glibc, which can be tricky and painful. I'd much rather deploy a Java app at that point.

So then I have come to the conclusion that Rich Hickey wasn't wrong: VMs offer some really nice features that you just can't get without them. They do present up-front distribution costs at times; but if you can nail that, your developers can continue to program and be productive, and have a clear, uniform path for getting features into the app without having to worry about the Cgo library land mines. (Full disclosure: I'm a Clojure fan. See what I did there?)

Popular Posts