Go Go Python Rangers - Comparing Python and Golang

7 min read

Python
None

Go (often referred to as golang) is awesome!

Let me explain why a Python fan of many years could say that. But to understand that we have to go back in time to see how my fascination with Python began.

Python - love at first sight

Pythonic love heart

Let’s move to the year 2002 when most of people were using 56kbps modems to chat on AIM or Gadu-Gadu and download mp3’s from Kazaa or eMule. I just started studying computer science and I saw Linux for the first time.

I was amazed like a child in a candy shop. You could do so much more in Linux than in the old Windows 98 that I had at that time. So I wanted to install it on my own computer at home.

I used my pocket money to buy Linux Magazine with Red Hat 7.3 installation CD. Imagine my disappointment when in the middle of the installation, the CD drive started to slow down and finally stopped.

That was when I saw Python traceback for the first time. I think it was an IOError because the CD was corrupted and couldn’t load some file.

I was sad. I tried to install it again and again. Every time the same exception popped up.

A broken feature in open-source software… it’s not a problem, it’s a challenge :)


Fortunately, Python traceback shows filenames and line numbers. So I could easily find where the error was in the source code of Anaconda, Red Hat’s installer written in Python.

When I opened the .py file, I was surprised that I could read it. I could even understand it without ever having read a tutorial of Python. At that time I was only able to program in C++ and Pascal, but learning those took a lot of hard work on my part.

To finish the story I have to boast that I modified the installer to omit corrupted files and I finally could use Linux at home. Python’s readability and flexibility impressed me so much that on that day, I became a Python fan for life.

“It’s not a problem, it’s a challenge” - The Golang Edition

A few months ago I’ve moved to another city to open a new STX Next office. In my newly rented flat in Gdansk, I don’t have a smart TV anymore. It’s not that bad because Kodi, a free and open-source media player running on my Raspberry Pi 3, is a very good replacement.

Unfortunately, the Link TV and Phone feature is missing in Kodi’s YouTube add-on. (If you haven't used this feature yet I would definitely recommend to try it.)

A missing feature in open-source software… it’s not a problem, it’s a challenge:
Python vs Go challenge accepted meme

I heard that Kodi’s add-ons are written in Python, so I thought it would be easy. The process of pairing the TV and phone is quite easy and well documented (DIAL protocol) and there are even Python implementations (e.g. xbmc-dial).

But the exchange of commands between paired devices is not a piece of cake. Surprisingly, Google didn’t publish any documentation.

After a long search, I finally found plaincast, a tool written in Go that plays only the sound from YouTube videos. When I opened the .go file I was surprised that I could read it. More importantly, I could understand it without even reading a tutorial of Go.

So I took it as a base and I’ve created kodicast, a standalone service that sits in-between YouTube and Kodi. You can check from the commit history that it only took me approx. 24 h in total.

That’s not bad, especially if you realize I had to familiarize myself with two different protocols and make changes in a program written in a language that I only heard of.

 

Go vs Python interview gif

Comparing Python and Go: same same ...

There are some similarities between Go and Python. You can find some resemblance between high-level types - slices and maps are like lists and dicts, but with static typing. Go’s range works as Python’s enumerate. And that’s it.

… but different ...

The differences between the two languages are much more numerous. Some of them can be shocking for a Python developer. For example, in Go there is no try-except. Instead, Go allows functions to return an error type in addition to a result.

        // getUUID returns a stable UUID based on the first MAC address
func getUUID() (*uuid.UUID, error) {
    itfs, err := net.Interfaces()
    if err != nil {
        return nil, err
    }
    // get the first interface with a MAC address
    for _, itf := range itfs {
        if len(itf.HardwareAddr) == 0 {
            continue
        }
        id := []byte(itf.HardwareAddr.String() + "-" + NAME)
        return uuid.NewV5(uuid.NamespaceOID, id)
    }
    return nil, errors.New("could not find interface with MAC address")
}
    

So when using a function, you first have to check if an error was returned or not. 

        deviceUUID, err := getUUID()
if err != nil {
    logger.Fatal(err)
}
    

Static typing is another thing that you have to get used to. Of course there are situations when you can’t be completely sure of the data type. For such situations, Go offers an empty interface (interface{}). It may hold values of any type, but when you want to use it (e.g. make some operations on it) you have to use type assertion to get the underlying value.

As an example, let’s look at parsing of some JSON data.

        func (kodi *Kodi) getPlayerId() (int) {
    resp, err := kodi.sendCommand("Player.GetActivePlayers", nil)
    if err != nil {
        return -1
    }
    // resp is a JSON [{"type":"video","playerid":0}]
    result := resp.([]interface{})
    for _, i := range result {
        // a map with string keys but values can be a string or a number
        // so we have to use empty interface as a value type
        item := i.(map[string]interface{})
        playerType := item["type"].(string)
        if playerType == "video" {
            return int(item["playerid"].(float64))
        }
    }
    return -1
}
    

There are a few more Go novelties that the Python developer will have to learn, such as:

  • pointers

  • structs (compound types)

  • goroutines (comfy concurrency)

  • channels (send messages between goroutines)

  • methods (Go does not have classes, but you can define methods on types)

  • closure

  • defer (replacement for try-finally)

… but still same

So why can the Python developer understand Go so easily? I think it’s because Go’s design follows similar principles.

Let’s compare the Go guiding principles and the Zen of Python. In both languages reducing clutter and complexity is a priority.

Go’s clean syntax ruler leads to high readability, which is so valued by Pythonistas (Readability counts in the Zen of Python). Also, Go’s orthogonality, a trend to keep a relatively small set of basic building blocks, favors simplicity over complexity (Simple is better than complex). Static typing is consistent with the rule of explicitness as well (Explicit is better than implicit).

“And never make me choose, because I may make a bad choice”

Many CTOs and software architects have to choose a programming language when they start a new project or create a startup. Python is very good for Web and Data Science. However, Go is much faster in terms of performance than any interpreted language such as Python.

Golang vs Python meme

To quote HappySad, my favorite band, “Never make me choose, because I may make a bad choice”. In this case, I think you don’t have to choose.

In my opinion using both Python and Go would be a powerful mix. You could use Go to write the code for which performance is critical, then use Python for the rest. A microservices architecture or even a serverless approach is probably the best way of mixing Go and Python together.

Go Go Python Rangers!

The similar design principles of Go and Python make the transition from Python to Go quite enjoyable. I hope to see more projects that mix Python and Go. So if you’re a Python Ranger - why not give Go a go?

nearshoring ebook
Author

Wojciech Lichota

Head of Service Delivery

More articles about Python