🧬 Generics в Go
Generics --- это механизм, позволяющий писать функции и типы, которые работают с разными типами данных, без дублирования кода. Они обеспечивают гибкость, безопасность типов и универсальность решений.
📌 Зачем нужны generics
- Позволяют одной функции работать с несколькими типами данных
- Снижают дублирование кода
- Повышают читаемость и безопасность
- Используют constraints для ограничения допустимых типов
🧩 Синтаксис generics
func name[T constraint](value T) T {
// ...
}
Где:
T- параметр типаconstraint- набор допустимых типов
Возможны несколько параметров типа:
func combine[T A | B, U C](a T, b U) {
// ...
}
📝 Пример простой generic-функции
func IsEqual[T comparable](a, b T) bool {
return a == b
}
IsEqual(2, 2)
IsEqual("foo", "bar")
IsEqual('a', 'b')
IsEqual[uint8](4, 4)
🛠 Создание собственного ограничения (constraint)
Ограничения создаются через интерфейсы:
type Integers32 interface {
int32 | uint32
}
func SumNumbers[T Integers32](arr []T) T {
var sum T
for i := 0; i < len(arr); i++ {
sum += arr[i]
}
return sum
}
Использование:
nums := []int32{1, 2, 3}
total := SumNumbers(nums)
🚫 Ограничения и псевдонимы типов
type Integers32 interface {
int32 | uint32
}
type MyInt int32
nums := []MyInt{1,2,3}
// Ошибка: MyInt не входит в Integers32
🔍 Приближённые типы (approximation)
Использование тильды (~) позволяет определять типы по их базовому
типу:
type Integers32 interface {
~int32 | ~uint32
}
Теперь MyInt на основе int32 будет работать.
🔒 Встроенные constraints (пакет constraints)
Constraint Описание
any любой тип
comparable типы, поддерживающие == и !=
Integer все целые
Float числа с плавающей точкой
Complex все комплексные числа
Ordered типы, поддерживающие <, >
🧱 Generic-структуры
Generics также поддерживаются в структурах:
import "golang.org/x/exp/constraints"
type MyArray[T constraints.Ordered] struct {
inner []T
}
func (m *MyArray[T]) Max() T {
max := m.inner[0]
for i := 0; i < len(m.inner); i++ {
if m.inner[i] > max {
max = m.inner[i]
}
}
return max
}
Использование:
arr := MyArray[int]{inner: []int{6, 4, 8, 9, 4, 0}}
fmt.Println(arr.Max())
✅ Итоги
- Generics уменьшает дублирование кода
- Constraints ограничивают допустимые типы
- Тильда
~позволяет указывать приближённые типы - Пакет
constraintsсодержит полезные ограничения - Generic-структуры дают мощный инструмент обобщённого программирования