Ответ
Дженерики, появившиеся в Go 1.18, — это механизм, позволяющий писать функции и структуры данных, которые могут работать с любым типом, удовлетворяющим определенным ограничениям (constraints).
Основная цель — написание обобщенного, но при этом типобезопасного кода, что позволяет избежать его дублирования.
Преимущества:
- Устранение дублирования кода: Больше не нужно писать одинаковые функции для
int
,float64
,string
(например,Min
,Max
, функции для работы со слайсами). - Типобезопасность: В отличие от использования
interface{}
, все проверки типов происходят на этапе компиляции, а не в рантайме. Это предотвращает множество ошибок.
Недостатки и когда быть осторожным:
- Усложнение кода: Чрезмерное использование дженериков, особенно с вложенными параметрами типов, может сделать код сложным для чтения и понимания.
- Не замена интерфейсам: Дженерики и интерфейсы решают разные задачи.
- Дженерики — для обобщенных алгоритмов и структур данных (одна и та же логика для разных типов).
- Интерфейсы — для полиморфизма поведения (разные типы реализуют одно и то же поведение по-разному).
Пример: обобщенная функция для проверки наличия элемента в слайсе
// [T comparable] — это ограничение (constraint).
// Оно означает, что тип T должен поддерживать операции сравнения == и !=.
func SliceContains[T comparable](s []T, val T) bool {
for _, v := range s {
if v == val {
return true
}
}
return false
}
// Использование:
SliceContains([]int{1, 2, 3}, 2) // true
SliceContains([]string{"a", "b"}, "c") // false
Итог: Дженерики — мощный инструмент для написания обобщенных алгоритмов и структур данных. Интерфейсы остаются лучшим выбором для полиморфизма поведения. Используйте их осознанно, чтобы улучшить, а не усложнить код.