Зачем используются интерфейсы в Go
Что проверяют
Понимаете ли вы неявную реализацию и знаете ли главное правило: интерфейс объявляется у потребителя.
Как отвечать
Интерфейс это набор сигнатур. Тип реализует его автоматически, если имеет нужные методы: implements писать не надо, и зависимость от пакета с интерфейсом не нужна. Это позволяет описать интерфейс для чужого типа, которого вы не контролируете.
Зачем: подменять реализацию в тестах, скрывать детали за абстракцией, писать функции, работающие с любым подходящим типом.
Главное правило, ради которого вопрос и задают: интерфейс объявляется там, где он используется, а не рядом с реализацией. Потребителю нужен один метод, значит и интерфейс из одного метода:
type Storer interface { Save(ctx context.Context, j Job) error }
func Import(ctx context.Context, s Storer) error { ... } // в тесте передаём заглушкуОтсюда идиома «чем меньше интерфейс, тем полезнее»: io.Reader и io.Writer состоят из одного метода и потому применимы повсюду.
Технические детали, которые спрашивают следом: интерфейсное значение это пара из типа и указателя на данные, поэтому интерфейс, содержащий нулевой указатель, сам не равен nil и это классическая ловушка. Пустой интерфейс any принимает всё, а достать значение обратно позволяют утверждение типа и switch по типу.
Где спотыкаются
Объявляют большой интерфейс рядом с реализацией, копируя привычку из Java.
Попадают в ловушку с ненулевым интерфейсом, содержащим нулевой указатель.
Не различают, где методы объявлены на значении, а где на указателе, из-за чего тип неожиданно не реализует интерфейс.
Используют any вместо конкретного интерфейса и теряют проверку компилятором.