Если вы знакомы с C++, то наверняка слышали о шаблонах. Шаблоны. Простая идея шаблонов заключается в передаче типа данных в качестве параметра, чтобы нам не приходилось писать один и тот же код для разных типов данных. То же самое и с дженериками в Golang, которые представлены следующими тремя типами:

Тип параметра:

Прежде всего, давайте напишем простую функцию, которая принимает два целых числа в качестве параметров и возвращает минимальное из двух чисел:

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

Эта функция возвращает 1, что является минимальным значением:

Но если мы передадим 1.1 как одно из значений этой функции, это даст нам ошибку времени компиляции:

Это связано с тем, что функция ожидала получить целое число, а не число с плавающей запятой. Как решить эту проблему? Здесь вступают в действие параметры типа:

Для этого мы пока будем использовать отдельную функцию и позже вернемся к минимальной функции:

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

Что можно назвать так:

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

Эта функция возвращает любой заданный ей тип.

Итак, вот как параметры типа позволяют нам передавать любой тип функциям в Go.

Второй тип, о котором нам нужно поговорить, это:

Вывод типа:

Это в основном имеет дело с базовыми типами, например, в следующем фрагменте кода мы объявили новый тип fakeInt32, который в основном является int32, но наша функция не будет принимать fakeInt32, поскольку это не совсем 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
}

Но это дает нам ошибку времени компиляции:

Таким образом, вывод типа помогает нам справиться с этим, все, что нам нужно добавить оператор «~» перед ожидаемым типом, это гарантирует, что все типы, которые имеют int32 в качестве базового типа, также будут приняты.

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

Итак, вывод теперь будет:

Какой ожидаемый результат.

Теперь обращаем внимание на:

Набор типов:

Вернемся к функции min:

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

Это приведет к ошибке времени компиляции, поскольку оператор ‹ не определен для всех типов:

В этом нам может помочь набор типов, мы можем определить набор типов следующим образом:

type typeSet interface {
~int32 | float32
}

Итак, это определяет набор типов, который включает типы, поддерживающие оператор ‹, функция будет выглядеть так:

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

И это дает ожидаемый результат:

Итак, это все о дженериках в Go.