# 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;
