Вопрос с собеседования · Go

Как работают интерфейсы в Go и что значит неявная реализация?

JuniorМетоды и интерфейсы
Ещё спрашивают так:
  • Почему в Go не пишут implements?
  • Где в Go объявлять интерфейс — у реализации или у потребителя?
Коротко

Тип удовлетворяет интерфейсу автоматически, если у него есть все методы интерфейса — без слова implements. Поэтому интерфейсы объявляют у потребителя и делают маленькими (io.Reader — один метод). «Принимай интерфейсы, возвращай структуры».

  • Проверка соответствия на этапе компиляции: var _ io.Reader = (*MyType)(nil)
  • Маленькие интерфейсы легко реализовать и подменить в тестах
  • Интерфейсное значение — пара (тип, значение)

А ещё Похоже на Protocol в Python и структурную типизацию в TypeScript

Подробно

Неявная реализация развязывает пакеты: пакет-потребитель объявляет нужный ему интерфейс из одного-двух методов, и любой тип из чужого пакета подходит, если у него есть эти методы. Библиотеке не нужно знать о ваших интерфейсах.

Маленькие интерфейсы стандартной библиотеки: io.Reader, io.Writer, fmt.Stringer, error, sort.Interface. Из них собираются большие встраиванием: io.ReadWriteCloser.

Где объявлять. В Go принято объявлять интерфейс там, где он используется, а не рядом с реализацией: «принимай интерфейсы, возвращай конкретные типы». Интерфейс «на всякий случай» с одной реализацией — лишний.

Внутреннее устройство. Значение интерфейса хранит указатель на таблицу методов конкретного типа (itab) и указатель на данные. Вызов метода — косвенный, через таблицу.

Пример

type Notifier interface {
    Notify(ctx context.Context, msg string) error
}

type OrderService struct{ n Notifier }   // зависит от абстракции

type EmailSender struct{ ... }
func (e *EmailSender) Notify(ctx context.Context, msg string) error { ... }

svc := OrderService{n: &EmailSender{}}   // никакого implements

Что хотят услышать

  • Неявное удовлетворение интерфейсу.
  • Маленькие интерфейсы и объявление у потребителя.
  • Устройство интерфейсного значения.

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

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✗Тип реализует интерфейс через ключевое слово implements
  • ✗Соответствие интерфейсу проверяется только во время выполнения программы
  • ✓Тип реализует интерфейс автоматически, если у него есть методы
  • ✗Интерфейсы в Go лучше делать большими и общими

Что спросят дальше

Связанные вопросы

Партнёр платформы

Разбор собеседования с sotto

После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.

Разбор собеседования