Photo by frdm . on Unsplash

From Python to Go

Alex Reid
Kudos Engineering
Published in
6 min readJun 7, 2019

--

Q: Which is better? Python or Go?
A: Yes.

Despite what some would like you to believe, there’s no such thing as the ‘best’ language for anything. You could even write your web server directly in assembly (please don’t, though). So rather than a no-holds-barred title fight to crown the one true web development language, this article is instead going to be a look at some of the similarities and differences I’ve spotted while getting started with Go from the perspective of a vaguely experienced Python developer.

Go and Python are worlds apart. Right? Python is an interpreted, dynamically-typed language, while Go is compiled and statically typed. Python has a clean, elegant syntax making smart use of whitespace to delimit blocks, while Go liberally seasons code with curly braces in the best traditions of C. But both languages share some philosophies that makes them feel closer than they might at first appear.

Anybody who’s spent any time with Python has probably run into The Zen of Python. Any Python developer who finds themselves feeling un-Pythonic can open their trusty REPL and type import this to be reminded of it:

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren’t special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one — and preferably only one — obvious way to do it.
Although that way may not be obvious at first unless you’re Dutch.
Now is better than never.
Although never is often better than
right now.
If the implementation is hard to explain, it’s a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea — let’s do more of those!

The good news is that if you’re already writing clear, well-structured Python, Go will come somewhat naturally. The Zen of Python is mostly just generally-applicable good practice when writing software and not specific to Python in any way (except, possibly, the bit about being Dutch).

So, with that in mind, let’s have a tour of some of the big, scary differences between Python and Go so that we might be less afraid.

Typing

As previously mentioned, Python uses dynamic typing¹. Code generally doesn’t care about the explicit type of any object, and instead values are duck typed — our code attempts to access properties of objects when the program runs, and if that object doesn’t have that property, an exception is raised. In contrast, Go uses static typing. The compiler knows the type of every variable ahead of time, so it can check to make sure that types match up during the compilation phase. If your types don’t match, your code won’t even compile.

This can feel limiting at first, but thankfully Go allows you to easily specify lightweight interfaces. If you specify interfaces rather than more concrete types in your function signatures, any struct which implements the interface can be used, which can make your code vastly more flexible.

We also in Go always have the option of using the escape hatch of the empty interface, which every struct implements, allowing us to pass untyped data between functions. However, to access any field or method on the struct, we have to make type assertions, and (hopefully) do something sensible when the type assertion fails. Because this then complicates all code dealing with the empty interface with error handling, it’s best used judiciously.

Even with all this, I’ve still run into the odd case here and there where something naturally expressible in Python is much more painful in Go, but there is a draft proposal to add parametric polymorphism to Go, which would alleviate much of this pain.

¹ If you’re already using MyPy or similar to take advantage of the support for type annotations in recent versions of Python, you’re already ahead of the game here, and thinking about types in Go will come much more naturally.

Photo by Daniel Watson on Unsplash

Error Handling

In Python, exceptions may be raised at any time, which will unwind the call stack until a matching exception handler is found. Sometimes, an innocuous function call will raise an exception you weren’t expecting, and it bubbles up and eventually (in the case of most web frameworks) gets caught by a framework-provided generic exception handler. In Go, on the other hand, errors are explictly returned and must be either checked or deliberately ignored. In many ways, this is more Pythonic than Python itself, since ‘explicit is better than implicit’.

The downside of this is that idiomatic Go code is often littered with error checks. Because there’s so much checking of errors, that can lead to a tendency to make actually handling those errors as brief as possible, sometimes at the expense of correctness or usability. if err != nil { return err } is quick and easy to write, but simply bubbling errors up to the callers of your function like this discards important information about the sequence of events that led to the error.

The draft proposal to add cleaner error handling to Go, along with the proposal for more expressive error values should vastly improve this situation, maintaining the explicitness of Go’s current error handling while enabling code to contain much less error handling noise.

Photo by Olivier Guillard on Unsplash

No Monkey Patching

In Python, we often mock out parts of objects under test by monkey patching (often using the mock package in the standard library). In Go, however, monkey patching is not an option. (Or at least, not an option you want to pursue.)

Instead of monkey patching, we can make use of dependency injection. For example, rather than constructing an API client inside our function, we can simply take one (or even better, accept anything that implements a limited client interface) as a parameter. The good news is that this pattern is also a very powerful way to work in Python, so you may well already be doing it. It avoids some of the failure cases and undue coupling between tests and code under test that can occur with monkey patching.

So, what’s similar?

Standard Library & Community Packages

In Python, we’re used to the idea that the language has ‘batteries included’. A rich standard library allows us to do a huge number of useful things without ever installing a third-party library. The good news is that Go shares this philosophy, and has a very rich standard library. I haven’t found any significant gaps compared to Python, especially when it comes to web development.

Another benefit of Python is that we have a huge array of packages shared by the community that we can use, and over the years, a dizzying array have been created. Go’s ecosystem still feels a bit younger than Python’s, but is still fairly large and comprehensive. Package management has a different feel to it, as there’s no centralised repository like PyPI, but tools like Go’s new module support make it convenient to use third-party modules (with some nice advantages, like the ability to use multiple versions of a library side by side).

And a few more things…

Syntax! Even though the syntaxes of the two languages differ broadly, I think they’re both designed with similar goals — the principal that things should be unsurprising, and that the language should make careful use of punctuation, rather than liberally sprinkling sigils everywhere.

Developer tools are great for both, with great editor support and usable debuggers, plus comprehensive linters with sensible defaults.

Not So Different

So, while Go and Python are very different on a technical level, they share a perhaps surprising amount of their outlook on what good code and good language design looks like. If you’re coming from a professional approach to Python development, prioritising readability rather than clever one-liners, Go won’t be too much of a shock.

If you like what you read and think you could contribute to our team at Kudos then take a look at our careers page to see what roles we currently have open.

--

--