Материал проходит вычитку — возможны неточности.
Урок 47 из 118

Проектирование интерфейсов

Аня оставила на ревью развёрнутый комментарий: контракт описывает тот, кто использует, а не производитель. Миша переделал слой хранилища по её схеме, и обработчики избавились от лишних проверок типов.

Главная мысль

интерфейсы в Go делают маленькими и объявляют у потребителя — тот, кто использует значение, описывает, что ему нужно, а не производитель навязывает свой контракт.

Маленькие интерфейсы

Go

Стандартная библиотека построена на однодвухметодных интерфейсах. Маленький интерфейс легко удовлетворить, легко имитировать в тестах, и его назначение видно из имени. Большой интерфейс с десятком методов подходит одному типу и бесполезен остальным.

Объявлять у потребителя

// service.go — в пакете, который ИСПОЛЬЗУЕТ данные
type repository interface {
    FindFile(id string) (FileMeta, error)
}

type Service struct {
    repo repository
}

Интерфейс объявляется там, где его используют, а не рядом с реализацией. Потребитель описывает минимальный контракт, который ему нужен — и любая реализация, подходящая под него, работает без изменения кода производителя. Это переворачивает привычную иерархию классов: не «класс объявляет, что он умеет», а «потребитель объявляет, что ему нужно». Так Аня предложила поступить с хранилищем: контракт описывает тот, кто хранилище использует.

Принимай интерфейсы, возвращай конкретные типы

Функции принимают интерфейсы (гибкость: работает с любой реализацией) и возвращают конкретные типы (вызывающий получает полный набор возможностей и не нуждается в type assertion). Возвращать интерфейс стоит только когда реально нужно скрыть реализацию.

В следующем уроке

Вы узнаете:

  • как переход на generics заменяет interface{} в сигнатурах
  • как встраивание интерфейсов собирает ReadWriter
Задание · вопросы

Проверьте себя

Вопрос 1 из 3

Когда интерфейс мешает, а не помогает?

Вопрос 2 из 3

Какой принцип иллюстрирует io.Copy(dst io.Writer, src io.Reader)?

Вопрос 3 из 3

Почему strings.ToUpper(s string) string принимает конкретный string, а не интерфейс?

Итоги

Интерфейсы: маленькие, у потребителя, принимаются функциями, а возвращаются конкретные типы. Это и есть идиоматичный Go.

Наш сайт собирает куки. Чтобы тебе было удобнее им пользоваться. Нажимая на кнопку, ты даёшь разрешение собирать куки