Go Doesn't Have Generics

Go doesn’t have generics. This isn’t news, but it’s more foundational than many might realize.

It is widely known that Go does not have generics. I’ve known this since I started with Go, but I recently found that the types, even when using type assertions, are a little stricter than I expected. Let me explain.

🔗 interface{}

Go has interfaces, which are sort of like Java interfaces, except that your code automatically matches them, as opposed to opting into them. There’s a thing where you define an empty interface (interface{}) which means every type satisfies the interface and thus can be used in place of those types. Here is an example:

var foo interface{}
foo = "frew"
fmt.Printf("%#v\n", foo);
foo = 1
fmt.Printf("%#v\n", foo);
foo = true
fmt.Printf("%#v\n", foo);
foo = []int{1, 2, 3}
fmt.Printf("%#v\n", foo);

Ok great. So the next interesting thing is that you can use type-assertions to get the underlying, typed value out. Here’s what I mean:

var foo interface{}
foo = 3
var bar int = foo.(int)

Without the .(int) on the third line the above would fail to compile. This gets interesting with complex types (slices, maps, etc.)

While you can put an int in an interface{}, you cannot put a map[string]int in a map[string]interface{}. The following fails to compile:

var foo map[string]interface{}
foo = map[string]int{}

Fundamentally, in Go the type system only ever goes two layers deep, the type of the variable, and the type of the underlying value. So in the above the variable is a map[string]interface{}, which is a distinct type from map[string]int. The fact than you can have an interface{} variable holding an int value does not mean that you can have a type containing an interface{} match a distinct type containing something else.

Anyway, all of this is just to say that you need to be especially careful with interface{} in complex types.

As a side note I am not looking forward to Go getting generics. Much of what keeps the language simple today is the fact that people just cannot build super-abstract code without generics. I suspect that once we get real generics Go code on the internet will stop being the simplicity focused code it is today and instead become abstraction behemoths. I hope I’m wrong.

(The following includes affiliate links.)

If you don’t already know Go, you should definitely check out The Go Programming Language. It’s not just a great Go book but a great programming book in general with a generous dollop of concurrency.

Another book to consider learning Go with is Go Programming Blueprints. It has a nearly interactive style where you write code, see it get syntax errors (or whatever,) fix it, and iterate. A useful book that shows that you don’t have to get all of your programs perfectly working on the first compile.

Posted Mon, Nov 12, 2018

If you're interested in being notified when new posts are published, you can subscribe here; you'll get an email once a week at the most.