Параметры типа
Один и тот же маленький хелпер был скопирован в коде «Полки» восемь раз — под разные типы. Миша переписал его одной функцией с параметром типа и оставил на ревью Ане.
дженерики добавляют параметры типа — [T any] — которые позволяют написать одну функцию или тип для любого T, при этом результат сохраняет конкретный тип, а не превращается в any.
До и после
До Go 1.18 единственным способом написать функцию «для любого типа» был interface{} (нынешний any) — с потерей типизации:
func firstAny(s []any) any { return s[0] }
Дженерики позволяют написать один раз, параметризовав тип:
func first[T any](s []T) T {
return s[0]
}
fmt.Println(first([]int{1, 2, 3})) // 1 — вернулся int, а не any
fmt.Println(first([]string{"a"})) // a
[T any] — список параметров типа: T — имя параметра, any — ограничение. Компилятор проверяет тип на этапе сборки, а результат сохраняет конкретный тип. Главное отличие от any — типизация не теряется: вызов first([]int{...}) возвращает int. Для восьми копий хелпера в «Полке» это значит: одна функция вместо firstStr, firstInt, firstFile и остальных.
Что дают дженерики
- Безопасность: компилятор проверяет типы; ошибка
first([]int{}) + "строка"ловится на сборке, а не в рантайме. - Один код вместо N копий: не нужно писать
firstInt,firstStr,firstFile. - Конкретный результат: вызывающий получает
T, а неany— без assertion.
Параметры типа у функций
func contains[T comparable](s []T, v T) bool {
for _, x := range s {
if x == v {
return true
}
}
return false
}
Здесь ограничение comparable — потому что с T сравнивают через ==, а any этого не разрешает. Про ограничения — следующий урок.
Вы узнаете:
- почему
any-версия хелперов всё ещё встречается - как вывод типов работает в
first([]int{...})
Проверьте себя
Компилируется ли вызов first(nil)?
Что дают дженерики по сравнению с any?
правильных ответов
Дженерики — параметры типа; одна функция вместо копий; результат — конкретный тип, без потери типизации.
10 000 ₽ · 60 минут · онлайн