Clojure vs Go - Clash of the Titans!
If you are new to either of these programming languages; trust me when I say Golang and Clojure are both titanic.
Over the last few years, I've had the pleasure of freely exploring pretty much every major language released. I'm rather a jack-of-all-trades (and master of none!), which gives me the benefit of being able to compare languages in depth. Whilst I will try to be objective for the majority of the article here, I do have personal opinions on both of these langs, which I will explain later.
If you are experienced in both of these languages, this article most likely will not teach you anything. This post is aimed at developers who don't know either language, or are only familiar with one of them.
Before we dive on in, you can find Go here.
You can find Clojure here.
Clojure Overview
Clojure was first announced all the way back in 2007. The idea behind the release was to create a modern Lisp dialect, based on data immutability with an emphasis on concurrency. It is a functional, dynamic language that has grown enormously over the years to include powerful new abstractions such as transducers, protocols, and multimethods, to name just a few.
Clojure is based atop of the Java Virtual Machine (JVM), which gives a large number of benefits, but also some drawbacks in my opinion. The JVM infrastructure gives decades worth of performance optimisations, familiarity to many developers, and a vast ecosystem of libraries. Because Clojure can access all of the Java libs, and also has so many of its own both internally and community contributed, I would go out on a limb here, and say that Clojure definitely has one of the biggest ecosystems of any language.
I got to attend ClojureConj a few years back, and had the absolute privilege of meeting Rich Hickey - the original author of the language. I stand resolutely upon my opinion that he is easily one of the best and smartest computer scientists of our generation.
What is Clojure used for?
Clojure is actually a very general-purpose language. It was designed to be a hosted language; while it is hosted on the Java Virtual Machine, it can also be run on JavaScript engines (browsers and node.js).
With the addition of ClojureScript, Clojure can now be used to build web applications completely from the ground up, without using any other langs at all.
ClojureScript combines the reach of the JavaScript platform, the flexibility and interactive development of Clojure, and the whole-program optimisation of Google Closure to provide the most powerful language for programming the web.
Clojure is also extremely powerful when it comes to manipulating data. It is excellent at concurrency, or even avoiding concurrency altogether and making parallelism easy to achieve, especially as data is immutable.
Clojure is used by just about every kind of industry, except perhaps for very hardware constrained environments. There are even examples of Clojure monitoring systems on aircraft!
Benefits of Clojure:
- Extremely powerful,
- Open Source language,
- Epic concurrency primitives,
- Vast package ecosystem,
- Highly general purpose,
- Very performant,
- Fairly easy to learn,
- More friendly than other Lisps,
- Far more friendly than the JVM it's atop of,
- Excellent project manager in Leiningen,
- Can tap into Java's Gradle too.
Drawbacks of Clojure
- Based on the JVM (personal opinion!),
- Errors can be vague and unhelpful,
- Not as many learning resources available as Go,
- Compilation times can be excessive.
Clojure Syntax
For a simple example, we'll have Clojure spawn 10 threads that will sleep for a random amount of time, and then print a number between 0-9. For anyone already familiar with any of the Lisp dialects, you'll notice the similarity here. Also worth noting, that the example below actually has a fair level of similarity with the Golang code sample in the next section!
Go Overview
Go is an imperative, concurrent, statically-typed programming language introduced by Google in 2009. It’s been mentioned by the creators that Go was originally developed as a language for servers; but since its conception has grown, alongside its epic community, into something much more general purpose. Go's syntax and environment both adopt patterns one would more commonly see in dynamic languages.
To me, Go is just like short-hand C. Anything I could write in C, I could write in Go 5x faster, with minimal errors and actually enjoy writing it. (Rarely the case in C.) The garbage collection is very well done, and the lack of malloc
makes me extremely happy!
Many people moving to Go are coming from Ruby and similar object-oriented languages. There are a whole lot of stories littering the net, of rewrites from Rails cutting server costs by 90%, increasing reliability by 10x, and making response times 10x faster. Golang really is booming, and attracting some of the greatest talents in the industry.
What is Go used for?
Go is most definitely the more general purpose language of the two. Over the last few years, there has been a huge uptake in Golang from the web-app developer crowds! Being so flexible, Go can be used for pretty much all of the backend services any web app requires. From low-level database activity, to data processing and API development; Go can be used for it all! I personally have used Go to build out all of the backend services in an SOA application. Go is great for REST API development. The one caveat here, is that while Clojure can be used for frontend dev via CLJS, Go does not do well here at all.
Benefits of Go:
- Extremely powerful,
- Open Source language,
- Epic concurrency primitives,
- Amazing community surrounding Go,
- Simpler learning curve than Clojure,
- Makes building performant systems rather easy,
- Simplified C based syntax,
- Recently much improved package manager.
Drawbacks of Go
- Testing framework is lacking,
- Not good for full-stack dev; compared with Clojure/ClojureScript,
go get
package manager still needs work,
Go Syntax
Concurrency
The code examples above show off the basic concurrency primitives of both languages. Spawning lightweight threads in either language is a performant and safe way of using async threading. OS threads are typically quite heavy, and in the past languages had to use them. Now, however, the idea of goroutines
and core.async go blocks
enables us to spawn potentially millions of threads without killing our processor!
Both of these langs have very similar functionality when it comes to concurrent programming. One of the reasons I wanted to compare these two langs, is not just because I love them both, but because they are actually pretty similar, despite being different programming paradigms.
Whilst Go has goroutines
, Clojure uses go blocks
to spawn & run processes on separate lightweight threads. The fact that they even use the same word speaks volumes! Rich Hickey (the creator of Clojure) stated in the original blog post announcing core.async
; that the team took inspiration directly from Golang's concurrency primitives.
There is a fantastic article on Clojure concurrency here.
Clojure:
Everything within the go expression—called a go block—runs concurrently on a separate thread. Go blocks run your processes on a thread pool that contains a number of threads equal to two plus the number of cores on your machine, which means your program doesn’t have to create a new thread for each process. This often results in better performance because you avoid the overhead associated with creating threads.
Go:
The primary concurrency construct is the goroutine, a type of light-weight process. A function call prefixed with the go keyword starts a function in a new goroutine. The language specification does not specify how goroutines should be implemented, but current implementations multiplex a Go process's goroutines onto a smaller set of operating system threads, similar to the scheduling performed in Erlang.
Conclusion & My Personal Opinions
First up - Clojure. I got introduced to Clojure back in 2012 when I was at Couchbase. We used Clojure on some of the internal tooling, and it immediately caught my attention. At the time, I was a Ruby & Python dev, and a rather unskilled one, at that. The idea of different programming paradigms was alien to me, as I was only familiar with Object Oriented.
Clojure was the first functional language I learned, and because of that; I learned a hell of a lot about programming, and different programming patterns. The Lisp syntax didn't make any sense to me at the beginning, but I actually grasped it very quickly. Clojure isn't as difficult to learn as it might look upon first glance! This is one of the joys of Clojure!
I've used Clojure in production, and the performance was always something to brag about. The reliability and scalability ensured that Clojure will always have a place in my heart. Regrettably, I haven't had many chances over the last year to write much Clojure, but I'm going to make sure that it returns to the forefront of my daily dev.
And now, Go... From 2014 to 2016, almost every line of code I wrote was Go. Once again, I got introduced to Go whilst at Couchbase, as the genius engineers who work there rebuilt much of the backend from C to Go. The fact that the rewrite went from C to Go speaks volumes. I couldn't believe that Go could rival the performance of C! The fact was, Go is so much easier to learn than C, and does very nearly match C's performance!
Learning Go was much easier for me than learning Clojure. Go being an imperative language, allowed me a slightly more familiar, and less steep learning curve than the functional paradigm of Clojure. One of the biggest reasons Go was easier to learn was actually because there were many more resources available online to learn from. The Go community rocketed ahead of Clojure in terms of resources, content and engagement.
I have built and maintained production apps built in Go with various functionalities. While I was building out my last startup 3 years ago, we used a service oriented architecture, and built lots of smaller services in Go that linked together to form a robust, performant system. It was immensely satisfying!
If you were to ask me now, "Which language do you prefer?":
I have to say, I really would struggle to answer. As I haven't been able to write much Clojure recently, I guess I would have to choose Go. Believe me - that was not an easy answer to give!
I would love to hear about your preferences on Go vs Clojure. Please drop a comment in the section below and let me know your thoughts! Or if you would like to argue with me further, feel free to reach out to me on robin@status.im.
Thanks for reading!