Go vs. Python: How to choose

Can’t decide between Go’s speed or Python’s conveniences? Here’s how to pick the right language for your project

Go vs. Python: How to choose
Thinkstock

When it comes to ease and convenience for the developer and accelerating the speed of development, two programming languages rise above the pack—Python and Go. Today Python is a mainstay of scripting, devops, machine learning, and testing, while Go is powering the new wave of container-based, cloud-native computing.

Sometimes the choice between Python and Go is obvious: Choose Python for its rich ecosystem, choose Go for its execution speed. But sometimes the choice isn’t so obvious. In this article, we’ll run through the key differences between the two languages, and highlight the pros and cons to help you choose the right language for the job at hand.

Go vs. Python: Developer convenience

Python and Go share a reputation for being convenient to work with. Both languages have a simple and straightforward syntax and a small and easily remembered feature set.

Both Python and Go also have a short edit-compile-run cycle. Python has no compilation phase—it’s interpreted—so scripts execute almost immediately. Go compiles ahead of time, but its compilation phase is far faster than that of languages like C++. Go feels more like a scripting language to work with than a language compiled ahead of time.

Python uses dynamic-typing features, making it easier to quickly prototype applications. Labeling things with types is optional, and can be done to enforce additional program correctness (a good idea with large projects), but it’s never required. Larger codebases can become unwieldy without types.

In Go’s case, typing is strict, but readily inferred in most cases, so it’s less cumbersome. It also means larger code bases are easier to manage out of the box, because Go programmers have followed in the tradition of using types. On the other hand, Go lacks generics, so some kinds of code that would be more concisely expressed in other languages—including Python—become more verbose and boilerplate-y in Go.

Go vs. Python: Runtime speed

If there’s one area where Go beats Python hands down, it’s execution speed. Go is an order of magnitude or more faster than Python, even without any optimizations on the developer’s part. Go compiles directly to native machine code, while Python’s runtime dynamism is difficult to optimize for speed.

Nevertheless, Python can be “fast enough” for many common tasks, so it’s worth benchmarking a Python implementation for your use case. Many of the most performance-intensive jobs that Python is used for aren’t executed in Python itself, but through libraries written in C or C++. Also, the PyPy runtime, a drop-in replacement for the conventional CPython runtime, can provide significant speedups for long-running applications like web servers, even where Python’s dynamism is in heavy use.

Go vs. Python: Deployment

Go was designed from the outset to allow compiled apps to be readily deployed as stand-alone binaries across multiple platforms. Python, by contrast, was originally conceived as a scripting language, so Python programs require the Python runtime.

Python lacks a native solution for deploying a script as a stand-alone executable, but you can turn to third-party libraries like PyInstaller for that. Also, container solutions like Docker make it a little easier to package a Python app with its runtime.

Go vs. Python: Project management

Another bonus baked into Go from the beginning: modern software project management techniques. Quick command-line actions create a new Go project repository and manage its dependencies. It’s worth noting that Go hasn’t always had good support for dependencies and reproducible builds, but the modules system, introduced in Go 1.11, now provides a common mechanism for working with different versions of libraries.

In some ways Python suffers from the opposite problem: A plethora of project management and versioning tools often results in confusion about which tools and methods are best for a given job. On the plus side, it also means you’re not straitjacketed into doing things a particular way.

Go vs. Python: Asynchronous programming

Asynchronous operations—executing one task while waiting for another to complete—help I/O-bound code, like network services, run more efficiently.

Go has supported async natively from its inception by way of goroutines, a language syntax feature. Goroutines let you run many small operations side by side, with a native communication primitive, channels, to synchronize operations between them. Go also comes with tooling to reduce accidental misuse of those features; you can still write code that deadlocks or has race conditions, but it’s easy to catch most common mistakes of that kind.

Python recently gained language-level support for asynchronous behavior with the async/await keywords. Before that, asynchronous programming was possible in Python, just not straightforward. That means library support for modern Python async idioms isn’t as advanced as it could be, since it’s a latecomer to the language. But support is improving as more libraries become async-compatible and the non-async versions of Python fall out of support.

Go vs. Python: Error handling and debugging

Python and Go have profoundly different philosophies for error handling.

In Python, errors are first-class objects, and they propagate up the application’s call chain whenever the app throws an exception. This makes error handling optional, so the programmer must decide which cases will be handled and handle them manually. By the same token, Python’s approach also makes it possible to write more flexible error handling mechanisms that don’t clutter up each call site.

With Go, every function returns the value for the function itself, as well as a possible error object. Go programs typically have explicit annotations about possible error conditions at function call sites, so code has unambiguous error handling. The downside of this is verbose code. Go also has the panic/recover keywords for handling extreme situations that warrant killing the program outright, though of course they’re not meant to be used as profusely as Python exceptions. Go 2.0 may feature new error handling mechanisms that cut down on the verbosity, but that revision of the language is still a long way off.

Go vs. Python: Testing

Not all modern software development draws on unit and integration tests, but projects that do are more robust. Go and Python both provide native mechanisms for unit testing. For Go, there’s the native testing package. For Python, there‘s the unittest framework. 

Go includes test-coverage metrics as part of testing; with Python, you need a third-party package, coverage, to determine how thorough your test suite will be. On the other hand, Python has highly flexible built-in test options to complement its dynamism—e.g., it has assertions for checking a wide range of common conditions including raised exceptions. Python also uses a class to distinguish test code from application code, whereas Go uses function and file naming conventions.

Go vs. Python: Ecosystems

Over the years, Python and Go have gathered impressive libraries of third-party software around them that reflect their use cases and strengths.

Python has long been the go-to language for scripting and automation, as well as for building web services and creating easy-to-use interfaces between complex systems. This last category is how Python has come to dominate in data science and machine learning: Python makes it easy to glue together the large, complex libraries and workflows used in advanced data analytics and machine learning models.

Go’s success stories revolve around its async programming features and system-native speed. Web servers, networking applications, CPU-bound microservices, and system utilities are all great candidates for Go. Most of the software that powers modern, container-based application development—including Docker and Kubernetes—is written in Go.

One way to figure out whether to choose Go or Python is to see what existing projects written in them resembles your current effort. There’s a good chance much of what you’re trying to build has already been built by someone else, so you can pick not only the language but the supporting libraries that fits.

Finally, there’s nothing that says you can’t write in both Python and Go. You can use Go for performance-sensitive parts of your application, and provide Python wrappers or frontends for developer convenience and comfort.

Copyright © 2019 IDG Communications, Inc.