(Go)ing Generic: Writing type-free functions in Go

Shayan khan
CodeX
Published in
3 min readOct 29, 2022

If you are familiar with C++, you probably have heard about templates. Templates. The simple idea behind templates is that to pass the data type as parameter so that we do not have to write the same code for different data types. Same is the case with generics in Golang which are expressed as the following three types:

Type Parameter:

First of all, let’s write a simple function which takes two integers as parameters and returns the minimum of the two numbers:

package mainimport "fmt"func main() {
fmt.Println(min(1, 2))
}
func min(a int, b int) int {
if a < b {
return a
}
return b
}

This function returns 1 which is the minimum value :

But if we pass 1.1 as one of the values to this functions, it will give us a compile time error:

This is because the function expected to receive an int and not a float. How do we solve this problem? This is where type parameters kick in:

For this, we will be using a separate function for the time being and will return to the minimum function later on:

func returnNum[T any](a T, b T) T {
return b
}

Which can be called like:

func main() {
fmt.Println(returnNum[int32](1, 2))
}

This function returns any type that is given to it.

So, this how type parameters allow us to pass any type to functions in Go.

Second type we need to talk about is:

Type Inference:

This basically deals with the underlying types, for example in the following piece of code we have declared a new type fakeInt32 which basically int32, but our function would not accept fakeInt32 as it is not exactly int32:

func main() {
type fakeInt32 int32
var number fakeInt32 = 23
fmt.Println(returnNum[int32](number, 2))
}
func returnNum[T int32](a T, b T) T {
return b
}

But this gives us a compile time error:

So, type inference helps us to deal with this, all we have to add a “~” operator in front of the expected type, this would make sure all the types which have int32 as the underlying type are also accepted as well.

func returnNum[T ~int32](a T, b T) T {
return b
}

So,the output now would be:

Which is the expected output.

Now, turning our attention towards:

Type Set:

Let’s get back to the min function:

func min[T any](a T, b T) T {
if a < b {
return a
}
return b
}

This would give a compile time error as the < operator is not defined for all the types:

Type set can help us with this, we can define a type set like this:

type typeSet interface {
~int32 | float32
}

So, this defines a type set which involves types which supports the < operator, the function would look like this:

func min[T typeSet](a T, b T) T {
if a < b {
return a
}
return b
}

And it gives the expected output:

So, this was all about generics in Go.

--

--