Generic in Golang
Published: 2021-09-21 17:14:08

---
title: Generic in Golang
published: true
date: 2021-03-17 15:57:57 UTC
tags: 
canonical_url: https://devmarkpro.com/generic-in-golang
---

This year started with new news from the golang team, ["Adding Generic!"](https://blog.golang.org/generics-proposal).

If you have familiar with languages like Java or C#, you already familiar with the concept of Generics. For example, let's talk about sorting an array.

```go
package main

import (
    "fmt"
    "sort"
)

func main() {
    f := func(msg string, v []int) {
        fmt.Println(msg)
        for _, x := range v {
            fmt.Printf("%d ", x)
        }
        fmt.Println()
    }
    v := []int{10, 20, 100, 2, -1, 80}
    f("before sort", v)
    sort.Ints(v)
    f("after sort", v)
}

```

In the above code, we just used the `sort` package to sorting a slice of integers and print them out.

Everything looks good, right? So what if we wanted to sort a slice of other numeric types? The `sort` package has another function called [Float64s](https://golang.org/pkg/sort/#Float64s) (instead of `Ints`) but it's definitely not enough because we might need to do some sorting operation on other numeric types like `int32`.

So one approach is to define one function for each numeric type but we all know it's not the best idea! it's the place that `Generic` comes to picture.

Here's the definition of Generic in [Wikipedia](https://en.wikipedia.org/wiki/Generic_programming) :

> Generic programming is a style of computer programming in which algorithms are written in terms of types to-be-specified-later that are then instantiated when needed for specific types provided as parameters.

So the point of generic is, specify the type of the variable later and provide it as a parameter. That's exactly what we need for example in our sort function. The only thing that we need is to make sure our input **comply** our conditions. for example in the sorting scenario, it must be `numeric`.

Let's see how we can use generic in golang:

```go
func Bored[T any](s ...T) T {
    return s[0]
}

```

`Bored` function gives a slice of `T` as input and returns the first item in the slice as output. So WTH is `T`? first thing first, let's see how to use our `Bored` function:

```go
func main() {
    output := Bored("Hello", "Generics")
    fmt.Println(output)
}

```

That's great, a generic function is used exactly like a normal function! so let's talk about `T`: In this case, `T` is `string`. so what's the difference between generic and the old-fashioned go `interface{}`? I'll explain it with an example.

```go
func Bored(s ...interface{}) interface{} {
    return "I am string"
}
func main() {
    output := Bored(1,1.1,"hello", struct{}{})
    fmt.Println(output)
}

```

The difference is, `interface{}` could be anything but in the first function the type of `T` determined while passing the first element to it. if it's a string, the rest of them also must be a string. otherwise, you'll get an error while compiling the application.

```go

func Bored[T any](s ...T) T {
    return s[0]
}

func main() {
    output := Bored("Hello", "Generics", 1)
    fmt.Println(output)
}

```

output:

```bash
type checking failed for main
prog.go2:11:39: default type int of 1 does not match inferred type string for T

```

It's nice, isn't it? for Java or C# developers something like `Repository<T>` is pretty familiar which `T` is almost always one of the application's entities.

Back to `Golang`, the other type (instead of `any`) that introduced now, is `comparable`. It means the item must have the capability of being in `equality operation`.

```go
package main

import (
    "fmt"
)

func main() {
    fmt.Println(Equal(1, 1)) // true
    fmt.Println(Equal(2, 1)) // false
}

func Equal[T comparable] (input1, input2 T) bool {
    return input1 == input2
}

```

and same previous example we got a compile-time if pass multiple data type to this function:

```go
func main() {
    fmt.Println(Equal(1.1, 1))
}
/*
output: type checking failed for main
prog.go2:8:25: default type int of 1 does not match inferred type float64 for T
*/

```

I think the golang team provides some ways for developers to define the restriction of the type `T` themselves. for now, I just have seen `any` and `comparable`, if you know more typed parameter please share them in the comment section;