Ответ
Дженерики (generics), появившиеся в Go 1.18, — это механизм, который позволяет писать функции и структуры данных, работающие с любым типом из заданного набора, без дублирования кода.
Проблема, которую они решают:
До дженериков для написания универсального кода приходилось использовать:
- Дублирование кода: Создавать отдельные функции для каждого типа (
SumInts
,SumFloats
). - Пустой интерфейс (
interface{}
): Приводило к потере типобезопасности и требовало проверок типов в рантайме (type assertions), что снижало производительность и надежность.
Пример:
Без дженериков (дублирование):
func SumInts(nums []int) int {
var total int
for _, n := range nums { total += n }
return total
}
func SumFloats(nums []float64) float64 {
var total float64
for _, n := range nums { total += n }
return total
}
С дженериками:
// Определяем ограничение (constraint), которому должны соответствовать типы.
// В данном случае, тип должен поддерживать операцию сложения. ype Number interface {
int | int64 | float32 | float64
}
// T - это параметр типа, который должен удовлетворять ограничению Number.
func Sum[T Number](nums []T) T {
var total T
for _, n := range nums { total += n }
return total
}
Ключевые преимущества:
- Переиспользование кода: Один раз написанная функция работает для множества типов.
- Типобезопасность: Компилятор проверяет соответствие типов на этапе компиляции, а не в рантайме.
- Читаемость: Код становится чище и понятнее без
interface{}
и проверок типов.
Основные области применения:
- Структуры данных (слайсы, мапы, списки, деревья).
- Универсальные алгоритмы (сортировка, поиск, фильтрация).
- Функции-утилиты (работа с JSON, кэширование).