Ответ
Дженерики (обобщенное программирование) были добавлены в Go в версии 1.18. Они позволяют писать функции и типы данных, которые могут работать с любым типом из определенного набора, сохраняя при этом строгую типизацию во время компиляции.
Ключевые преимущества:
- Повторное использование кода: Можно написать одну функцию, которая работает с
[]int
,[]float64
,[]string
и т.д., вместо того чтобы писать несколько почти идентичных функций. - Типобезопасность: В отличие от использования
interface{}
, дженерики обеспечивают проверку типов на этапе компиляции. Это исключает необходимость в проверках типов во время выполнения (type assertions) и предотвращает паники. - Производительность: Код с дженериками обычно быстрее, чем аналогичный код, использующий рефлексию или
interface{}
, так как компилятор генерирует специализированный код для конкретных типов.
Пример: обобщенная функция для поиска элемента в слайсе
// [T comparable] - это объявление параметра типа T.
// `comparable` - это constraint (ограничение), которое означает,
// что тип T должен поддерживать операции сравнения == и !=.
func SliceContains[T comparable](slice []T, value T) bool {
for _, item := range slice {
if item == value {
return true
}
}
return false
}
func main() {
intSlice := []int{1, 2, 3, 4, 5}
fmt.Println("Contains 3:", SliceContains(intSlice, 3)) // true
stringSlice := []string{"apple", "banana", "cherry"}
fmt.Println("Contains 'orange':", SliceContains(stringSlice, "orange")) // false
// floatSlice := []float64{1.1, 2.2} // float64 тоже comparable
// fmt.Println("Contains 2.2:", SliceContains(floatSlice, 2.2)) // true
}
Нюансы и ограничения:
- Не все можно параметризовать: Например, методы структур пока не могут иметь параметров типа.
- Сложность ограничений: Создание сложных кастомных ограничений (constraints) через интерфейсы может снизить читаемость кода.
- Не замена
interface{}
: Дженерики не являются полной заменой интерфейсов. Интерфейсы по-прежнему являются основным инструментом для описания поведения (полиморфизма) в Go.