Обобщения на практике: подводные камни
Когда использовать обобщения и какие ошибки встречаются чаще всего
«Обобщения на практике: подводные камни» — бесплатный урок Go Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.
Избыточное использование обобщений
Не каждой функции нужны обобщения. Если используется только один конкретный тип, обобщённая функция добавляет сложность, но не приносит пользы. Предпочитайте конкретные типы и переходите к обобщениям, когда появляется дублирование.
Проверка типа внутри обобщений
Нельзя выполнять проверку типа или переключение типов внутри обобщённой функции для самого параметра типа — обобщения не являются шаблонами. Вместо этого используйте интерфейсы или пакет reflect.
// WRONG:
func Foo[T any](v T) {
if x, ok := v.(int); ok { // compile error
}
}Сравнимый тип не означает упорядоченный
comparable поддерживает только ==. Для использования < и > нужны cmp.Ordered или пользовательское ограничение. Распространённая ошибка — считать, что comparable поддерживает упорядочивание.
Метод не может добавлять параметры типов
Методы обобщённых типов используют параметры типа этого типа, но не могут добавлять новые. Если методу нужен дополнительный параметр типа, вместо него используйте функцию верхнего уровня.
// WRONG:
func (s *Stack[T]) MapTo[U any]() []U // compile errorНулевые значения и значение nil
Для параметров типов-указателей нулевым значением является nil. Для типов-значений это нулевое значение типа. Всегда обрабатывайте нулевой случай, не предполагая, что значение отлично от nil.
Наборы методов интерфейсов и обобщения
Обобщённая функция, ограниченная интерфейсом, может вызывать только методы, объявленные в этом интерфейсе. Добавление методов в конкретный тип не делает их доступными через ограничение.
Разрастание инстанцирования (формы GC)
Go использует общие реализации для типов с одинаковой формой GC (например, все типы-указатели используют одну реализацию). Для примитивных типов создаются отдельные реализации, но такой подход Go сохраняет разумный размер двоичных файлов.
Any — это не interface{}
any — это псевдоним для interface{}, но обобщённая функция F[T any] не равна F(v interface{}): в обобщённой функции T является конкретным типом в месте вызова, поэтому информация о типе сохраняется.
Рекурсивные обобщённые типы
Go не поддерживает рекурсивные определения параметров типов, такие как type Tree[T Tree[T]]. Вместо этого используйте композицию:
type TreeNode[T any] struct {
Val T
Left *TreeNode[T]
Right *TreeNode[T]
}Предварительно инстанцированные вспомогательные функции
В коде, чувствительном к производительности, заранее инстанцируйте часто используемые обобщённые функции в качестве функций верхнего уровня, чтобы избежать повторных затрат на вывод типов (хотя компилятор Go хорошо с этим справляется).
Тестирование обобщённого кода
Тестируйте обобщённые функции с несколькими инстанцированиями: по одному для каждого отличающегося ограничения (int, string, пользовательский тип). Это позволяет выявить пограничные случаи, зависящие от ограничений.
func TestMap(t *testing.T) {
got := Map([]int{1,2}, double)
// test with strings too
gotS := Map([]string{"a","b"}, strings.ToUpper)
}Быстрая проверка
Почему нельзя выполнить переключение типов для обобщённого параметра типа T внутри обобщённой функции?
Повторение: проблемы обобщений
Основные моменты:
- Не используйте обобщения чрезмерно: конкретные типы проще, если тип используется один раз
- Внутри обобщённых функций нельзя выполнять переключение или проверку типа для T
- comparable не означает упорядоченный тип; для поддержки < используйте cmp.Ordered
- Методы не могут добавлять новые параметры типов
Изучай Go с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 51
- Уроки
- 203
Часто задаваемые вопросы
Урок «Обобщения на практике: подводные камни» бесплатный?
Да — полный текст урока «Обобщения на практике: подводные камни» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.
Чему я научусь в уроке «Обобщения на практике: подводные камни»?
Когда использовать обобщения и какие ошибки встречаются чаще всего Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Go Academy?
Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Обобщения на практике: подводные камни»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Go Academy?
Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Синтаксис параметров типов
- Ограничения: comparable и интерфейсы
- Обобщённые структуры данных
- Обобщения на практике: подводные камни