Ответ
Интерфейсы и дженерики — это два разных механизма для написания полиморфного кода в Go. Они решают разные задачи и имеют разные принципы работы.
Интерфейсы (Полиморфизм поведения)
- Что это? Интерфейс определяет контракт поведения — набор методов, которые тип должен реализовать. Он отвечает на вопрос: "Что этот тип умеет делать?".
- Проверка: Проверка соответствия интерфейсу происходит в runtime (динамическая диспетчеризация).
- Гибкость: Позволяют создавать гетерогенные (разнородные) коллекции. Например, слайс
[]io.Writer
может содержать и*os.File
, и*bytes.Buffer
.
// Интерфейс определяет поведение "умеет говорить"
type Speaker interface {
Speak() string
}
// Функция работает с любым типом, который удовлетворяет интерфейсу Speaker
func Greet(s Speaker) {
fmt.Println(s.Speak())
}
Дженерики (Параметрический полиморфизм)
- Что это? Дженерики позволяют писать функции и типы, которые работают с любым типом из заданного набора, сохраняя при этом строгую типизацию. Они отвечают на вопрос: "С какими типами данных работает этот алгоритм?".
- Проверка: Проверка типов происходит на этапе компиляции.
- Производительность: Код с дженериками обычно быстрее, так как компилятор генерирует специализированные версии функций для конкретных типов, избегая накладных расходов runtime.
// Дженерик-функция для поиска индекса элемента в слайсе любого сравнимого типа
func IndexOf[T comparable](slice []T, value T) int {
for i, v := range slice {
if v == value {
return i
}
}
return -1
}
Сравнительная таблица
Характеристика | Интерфейсы | Дженерики |
---|---|---|
Основная идея | Абстракция над поведением | Абстракция над типами |
Проверка типов | Runtime (динамическая) | Compile-time (статическая) |
Производительность | Небольшие накладные расходы в runtime | Близко к нативному коду без полиморфизма |
Коллекции | Гетерогенные (разные типы) | Гомогенные (один тип T в рамках вызова) |
Когда что использовать?
- Используйте интерфейсы, когда вам важна общность поведения (например,
io.Reader
,http.Handler
). - Используйте дженерики, когда вы пишете алгоритмы для структур данных (слайсы, мапы, деревья) и хотите сохранить типобезопасность и производительность.