Golang

Thoughts and observations about Golang after learning it for a couple of months.

"There are only two kinds of languages: the ones people complain about and the ones nobody uses."

Disclaimer: While I'm quite critical of Golang and its use I'm not going to say you shouldn't use it. It's more important for me that you like your tools and that your team is comfortable with the language you're using.

My Context: Business Services #

I'm writing from the context of writing business logic and microservices and this post is a collection of my observations and thoughts when learning and using Golang.

Syntax #

Yes, it's ugly. But, for me, it's not a big problem. If you write enough of it your brain will learn to work with it thanks to chunking.

It's still annoying especially when most of it is avoidable if you sacrifice the compilation time a little. I get it that's a tradeoff, so let's not stop the discussion of where the fine line should be between the speed of compilation and the DX.

Still, it's not a deal breaker. You can get used to it and even appreciate it from time to time like my appreciation for explicit error handling that I got out of Golang.

Not Simple #

My first problem with Golang marketing is that it's lying about being a simple language. It's fairer to say it's simplistic.

I'm going to recommend the excellent 100 Go Mistakes and How to Avoid Them by Teiva Harsanyi. If you're a Golang developer it's a must-read. My argument isn't that Golang is somehow different from other languages (it's not), but the fact that it's supposed to be a simple and well-designed language. Unfortunately, as with everything people do it has flaws. In the case of Golang, a lot of them are caused by oversimplifications of the language. If you read the book you will notice a pattern of "simple" language causing unexpected and unhandled consequences you will have to deal with in practice. Most of them are unintuitive and caused by a leaky abstraction affecting your code.

Learning Golang #

The second marketing claim is that it is really easy to learn. The truth is that because of its simplistic design and idiosyncrasies, it's just like any other language.
I've seen Golang code being written like Java or Python. It's easy to learn the basics, but with only that you get much worse code, performance and memory usage if you just used a more high-level language. You need to put a significant amount of time to learn how to write good code in Golang. It's not only about the syntax of the language but also philosophy around manual memory management and error handling.

Learning Golang is also riddled with distractions like arrays when in practice everyone uses Slices.
Someone needs to write "Golang: The Good Parts", especially after generics were added to the language, but until then it's pretty complicated to really get to know idiomatic Golang and how to use it effectively.

Manual Memory Management #

Yes, I know that Golang has a garbage collector—I'm talking about all this code and effort every Golang programmer has to put in to avoid even minuscule amounts of memory allocations all the time. The best example is the Reader interface that's supposed to be used by everyone for everything. Take a look at Readers in the Tour of Go

r := strings.NewReader("Hello, Reader!")

b := make([]byte, 8)
for {
n, err := r.Read(b)
fmt.Printf("n = %v err = %v b = %v\n", n, err, b)
fmt.Printf("b[:n] = %q\n", b[:n])
if err == io.EOF {
break
}
}

There are two problems with this if you're using Golang to write business logic in it:

  1. You need to pass an already allocated slice of memory to the Read function.
  2. It uses bytes slices regardless of your level of abstraction.

This is a really low-level API, but it's one that's encouraged as a best practice because you allocate b only once.
While Golang has a garbage collector it doesn't have all the configuration flags you would expect.
If you start allocating a lot of temporary objects it just won't work well.

Low-Level #

I've found posts by [Amos/fasterthanlime where he takes a look at Golang from the point of view of low-level programming and is even more critical than mine.

Over and over, every piece of documentation for the Go language markets it as "simple".

This is a lie.

High-Level #

I'm not sure where I stumbled upon it, but I heard that Golang is not getting traction from the C/C++/Java developers and most of its traction is coming from Python and Ruby developers picking it up. Not sure if that's true but I've managed to find Why was Golang adopted by Ruby and Python developers rather than C++ and C developers? so it's at least a somewhat common opinion.

When you see articles about why company X is switching to Golang the most common reason I can find is the performance. But, if you're going to write web services or microservices then the only benefit you will get is lower memory consumption. In my experience, Golang isn't particularly faster than even Node.js or Java. It will use less memory, but it won't be for free as you will need to write a lot of repetitive code for it.

While it can work in some situations I would argue that you should try really hard to optimize your existing platform before you jump into Golang expecting an easy win. But, there is No Silver Bullet. You will need to invest significant time and effort into Golang if it's going to work.
But, if performance is really a problem then Rust might be a better solution.

Parallelism #

So you're interested in goroutines and lightweight threads Golang has?

I really like the distinction that's made by Rob Pike in Concurrency is not parallelism talk. It's really great and will hopefully start to give you an idea that you won't get anything for free.

The biggest misconception I've seen people have is that they want easy parallelism and have those ideas of how easy it's going to be to get much better performance with goroutines.

In practice, most of your problems are not easy to parallelize, and even if they are it's not trivial. You can still get a deadlock with goroutines, not to mention the gotchas you have to learn there. If you're thinking about using channels or goroutines then you need to read at least 100 Go Mistakes and something more focused on concurrency. The worst thing I've noticed is that switching from unbuffered to buffered channels can have huge unintended consequences.

Rather than getting an exceptional performance, you're as likely to get a data race, but at end of the day your will use unbuffered channels anyway so I'm really not sure if there is a point in having all this complexity in your app. At least I'm comparing it to my limited knowledge of Erlang OTP when you have a lot of support for things going wrong. In Golang channels you're on your own.

In practice channels and goroutines are not used as much as you think either. They are incorporated into some higher-level abstractions, but in that case, they are just an implementation detail that shouldn't have anything to do with your code.

Summary #

I've learned enough Golang to have an informed opinion about it. I don't see myself using it for fun in my spare time so that's where I'm going to stop investing my time and effort.

But, I wouldn't mind using it and learning more about Golang if there was a reason for it at work. While this post focuses on the negatives I don't believe in perfect languages and I like Golang way more than Java at this point.

Personally, I think of Golang as being comparable to JavaScipt—which I still like. They use the same format (IEEE-754) for floating-point numbers. They have a lot of similar problems around closures and loops with asynchronous code. If I stumble into a problem where I need to work directly with bytes then Golang might be a better choice.
The biggest difference on the server is probably memory usage, but given that you're doing a lot of that manually in Golang it's not easy to compare.

If you're willing to add compilation then TypeScript on top of JavaScript will give you a great high-level language with a much better type system.

If you're writing low-level code then Golang probably should be avoided in favor of something like Rust.



Share on Hacker News
Share on LinkedIn


← Home


Want to learn more?

Sign up to get a digest of my articles and interesting links via email every month.

* indicates required

Please select all the ways you would like to hear from Krzysztof Kula:

You can unsubscribe at any time by clicking the link in the footer of my emails.

I use Mailchimp as a marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.