Generics in Go

Ahmad Berahman
Apr 27 · 5 min read

The Go team has released a draft design for type parameters, which are colloquially referred to as generics. It’s expected to be included in Go 1.18. While there might still be last-minute changes.

Go is a statically typed language, which means that the types of variables and parameters are checked when the code is compiled. Built-in types (maps, slices, channels) and functions (such as len, cap, or make) can accept and return values of different types, but user-defined Go types and functions cannot. If you are familiar with Java, C++, or another language with some variety of generics, the simplicity of Go’s type system has probably caused a few frustrations.

If you are familiar with dynamically typed languages, where types are not evaluated until the code runs, you might not understand what the fuss is about generics, and you might be a bit unclear on what they are. It helps if you think of them as “type parameters.” We are used to writing functions that take in parameters whose values are specified when the function is called. Similarly, we create structs where the value for the fields is specified when the struct is instantiated. Generics is the concept that it is sometimes useful to write functions or structs where the specific type of a parameter or field is specified when it is used.

Since the first announcement of Go, there have been calls for generics to be added to the language. Russ Cox, the development lead for Go, wrote a blog post in 2009 to explain why generics weren’t initially included. Go emphasizes a fast compiler, readable code, and good execution time, and none of the generics implementations that they were aware of would allow them to include all three. After a decade of studying the problem, the Go team thinks it has a workable approach outlined in the Type Parameters-Draft Design.

We’ll see how generics work in Go by looking at a simple stack. If you were to implement a stack for any type without generics, here’s what you’d do:

We can use it like this:

This works and prints out 30 true, but you can insert a value of any type into this stack, and if you want to do more than print out the value returned by Pop, you need to use a type assertion to convert it to the type that was inserted. Let’s see how Go generics make this stack type-safe:

There are a few things to note. First, we have [T any] after the type declaration. Type parameters are placed within brackets. They are written just like variable parameters, with the type name first and the type bound second. You can pick any name for the type parameter, but it is customary to use capital letters for them. Go uses interfaces to specify which types can be used. If any type is usable, this is specified with the new universe block identifier any, which is exactly equivalent to interface{}, but is only valid within a type constraint. Inside the Stack declaration, we declare vals to be of type []T instead of []interface{}.
Next, we look at our method declarations. Just like we replaced interface{} with T in our vars declaration, we do the same here. We also refer to the type in the receiver section with Stack[T] instead of Stack.
Finally, generics make zero value handling a little interesting. In Pop, we can’t just return nil, because that’s not a valid value for a value type, like int. The easiest way to get a zero value for a generic is to simply declare a variable with var and return it, since by definition, var always initializes its variable to the zero value if no other value is assigned.

Using a generic type is very similar to using a nongeneric one:

The only difference is that when we declare our variable, we include the type that we want to use with our Stack, in this case int. Now, v has a type int and not interface{}, so you can use it without a type assertion. Furthermore, if you try to push a string onto our stack, the compiler will catch it. Adding the line:

produces the compiler error:
cannot convert “nope” (untyped string constant) to int

Since generics are not officially released yet, they are not supported on The Go Playground. However, there’s a temporary “Go2Go” Playground where you can try out the generic stack.
Let’s add another method to our stack to tell us if the stack contains a value:

Unfortunately, this does not compile. It gives the error:
cannot compare v == val (operator == not defined for T)

Just as interface{} doesn’t say anything, neither does any. We can only store values of any type and retrieve them. To use ==, we need a different type. Since nearly all Go types can be compared with == and !=, a new built-in interface called comparable is defined in the universe block. If we change our definition of Stack to use comparable:

we can then use our new method:

This prints out:

You can try out this updated stack.

In the resource of this post, you can learn more about Go Generic with different titles, For instance: Use Type Lists to Specify Operators, Generic Functions Abstract Algorithms, Type Lists Limit Constants and Implementations

Conclusion

Adding generics clearly changes some of the advice for how to use Go idiomatically. The use of float64 to represent any numeric type will end. We will no longer use interface{} to represent any possible value in a data structure or function parameter. You can handle different slice types with a single function. But don’t feel the need to switch all of your code over to using type parameters immediately. Your old code will still work as new design patterns are invented and refined.

Since there are no production implementations of generics, it’s hard to say how they will affect performance. It’s likely that there will be some impact at both compile-time and runtime. As always, the goal is to write maintainable programs that are fast enough to meet your needs.

We took a look forward at generics and how they will change how we use Go to solve problems. The implementation isn’t released yet, so there’s still a possibility of additional changes, but they are likely to be minimal.

Geek Culture

Proud to geek out.

Sign up for Geek Culture Hits

By Geek Culture

Subscribe to receive top 10 most read stories of Geek Culture — delivered straight into your inbox, once a week. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Geek Culture

A new tech publication by Start it up (https://medium.com/swlh).

Ahmad Berahman

Written by

I have a dream to have a spectacular garden

Geek Culture

A new tech publication by Start it up (https://medium.com/swlh).

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

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