Rust Traits over Go Interfaces

Photo by Paul Einerhand on Unsplash

Reading back over traits in “The Book” of Rust (that has a biblical feel, doesn’t it?), I realized something that was totally impossible in Go: implementing traits for non-local types i.e. types that you did not create yourself. To see what I mean concretely, let’s say that we wanted to define a square method for floating-point numbers. Sure, it’s actually far fewer keystrokes to just multiply the value by itself, but let’s say we wanna be extra explicit (as things are often better that way). In Rust, we can simply define a trait Squared with a method square and impl that for f64.

A snippet of Rust code defining a “Squared” trait and implementing a “square” method on the “f64” type.
Rust square trait.

This code snippet is also available on the Rust Playground. Pretty straight-forward! However, this turns out to be impossible in Go, since — according to the compiler — you “cannot define new methods on non-local types.” What a buzzkill. For example, the following program will not compile.

A snippet of Go code defining a “squared” interface and implementing a “square” method on the float64 type.
Go square interface

(Also on the Go Playground.) This might seem totally minor and technical, but it actually has pretty profound effects on how you can use libraries or modules in each language. With Rust, you can always just impl the desired functionality on top of other people’s hard work. In true programmer fashion, you stand on the shoulders of giants. However, in Go, this isn’t allowed. Limiting extensibility can be seen as both a win and loss for that elusive Gopher ideal, “simplicity”, which would actually make a nice girl’s name when you think about it . On one hand, all code relevant to one specific type is written alongside that type. It’s easy to find, but, on the other hand, hard to update. If you need some open-source maintainer to implement a string method, well, you might have to go to buymeacoffee.com. On the other, other hand, needs will inevitably arise for a project and Go’s rather simple (for all the good and bad that entails) approach to interfaces leaves you with two, equally hack-y options. You can either type-alias to define your “own” local type or create a struct wrapper for the original type. Both are pretty ugly in my honest opinion.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store