Что такое дженерики в Go и зачем они нужны
Что проверяют
Понимаете ли вы, какую конкретную проблему закрыли дженерики и где они не нужны. Язык долго обходился без них, поэтому ценится не пересказ синтаксиса, а чувство меры: когда параметр типа, когда интерфейс, а когда честнее написать две функции.
Как отвечать
Дженерики появились в Go 1.18: функции и типы получили параметры типов с ограничениями. До этого обобщённый код писали через пустой интерфейс с приведением, и ошибка вылезала уже в рантайме, либо копировали одно и то же под каждый тип.
Ограничение это интерфейс, задающий множество допустимых типов. Тонкость, на которой режутся чаще всего: comparable разрешает только равенство и неравенство, а для сравнения на больше и меньше нужен cmp.Ordered.
func Max[T cmp.Ordered](s []T) (T, bool) {
var zero T
if len(s) == 0 {
return zero, false
}
m := s[0]
for _, v := range s[1:] {
if v > m {
m = v
}
}
return m, true
}Скажите про вывод типов: в вызове параметр обычно писать не нужно, он выводится из аргументов. Упомяните, что стандартная библиотека уже закрывает типовые нужды пакетами для срезов и карт и встроенными функциями минимума и максимума. И про реализацию: компилятор порождает код не на каждый тип, а на каждую форму представления в памяти, поэтому все указатели получают общую версию, и ожидать выигрыша в скорости от замены интерфейса дженериком не стоит.
Где спотыкаются
Берут comparable там, где нужно упорядочивание. Это ровно тот случай, когда пример, заученный по статье, не компилируется прямо на доске.
Пытаются объявить параметр типа у метода. Параметры есть у функций и у типов, но не у методов, обобщать нужно сам тип-приёмник. Из той же серии ожидания: специализации под конкретный тип нет, вывод идёт только из аргументов, а не из того, куда присваивают результат.
Тащат параметры типов везде. Если код работает с поведением, а не со структурой данных, интерфейс проще и читается лучше, а обобщённая обёртка, используемая с одним типом, это лишний уровень косвенности. Зрелый ответ называет области, где выигрыш реален: контейнеры, утилиты над срезами и картами, обобщённые обёртки результата.