Recently, the Go team announced an updated draft design for their Generics in Go proposal. It goes into a lot of details about why certain decisions were made, implementation details, etc.

In this article, my goal is to summarise the major upcoming changes, as the whole draft design can be a mouthful for many.

I will provide some code snippets to demonstrate the major features as well as give you the chance to experiment yourself with them, thanks to the new Go playground with support for generics.

Type Constraints in Generic Functions

Here’s how a generic function looks like without any constraints on the type parameter:

Try it out!

To add constraints on the generic type, you can demand that it implements a given interface:

Try it out!

To specify multiple type parameters, separate them by commas:

Try it out!

Constraints on multiple type parameters are written the same way you write function argument types:

Try it out!

And here’s how to specify different types for both parameters:

Try it out!

Type Lists & comparable

Instead of constraining types based on a set of methods, you can constraint them based on a set of supported types. For example, you could specify that you accept a generic type which can only be an int or a long.

This allows you to e.g. leverage operators like “less than”, “greater than”, which are only available for basic types in Go:

Try it out!

You also have an out-of-the-box constraint called comparable, which constraints types to those which support the == and != operators.

Try it out!

Interfaces using these constructs – type lists and/or comparable can be used only as type constraints, rather than e.g. function arguments.

Generic Types

Structs can be defined using a generic type. Once specified, in the type declaration, there is no need to specify the type for all the functions of the type:

Try it out!

You can also do that in interfaces. This is especially useful when a type constraint depends on itself.

E.g. you have a type constraint for T, which requires an Equal method, which accepts a T parameter:

Try it out!

In case you need to specify a type parameter, who has a state-modifying function (e.g. a setter), then you can specify a pointer type constraint:

Try it out!

Notice how this example above requires that you explicitly specify the type you’ll use in the function – FromStrings(Settable)

This is because whenever the type is not present as a function argument, the compiler cannot infer the actual type once the code is compiled. Hence, you need to explicitly specify it.

Conclusion

This article was purposefully succinct and straightforward. Hopefully, it will help you quickly get up-to-date on the latest generics draft design, while you’re drinking your morning coffee.

However, there is a lot of rationale behind any single design choice around generics in Go. If you are interested to dive deeper into this subject, check out the official draft design doc.

So, do you like the latest Go Generics draft design?

Let me know in the comments section below.