🟡 Средний · 2 очк. Интерфейсы
Где в Go рекомендуется определять интерфейс: в пакете с реализацией или в пакете-потребителе?
A В пакете с реализацией, рядом с типом
B В пакете-потребителе, где интерфейс используется; принцип "accept interfaces, return structs"
C В отдельном пакете interfaces
D Не имеет значения
Объяснение вопроса

В Go принято определять интерфейсы на стороне потребителя (consumer), а не рядом с реализацией. Это следствие неявной реализации интерфейсов:

// пакет storage - возвращает конкретный тип
package storage

type PostgresRepo struct { db *sql.DB }
func NewPostgresRepo(db *sql.DB) *PostgresRepo { ... }
func (r *PostgresRepo) GetUser(id int) (*User, error) { ... }
func (r *PostgresRepo) SaveUser(u *User) error { ... }

// пакет service - определяет только то, что ему нужно
package service

type UserGetter interface {
    GetUser(id int) (*User, error)
}

func HandleGetUser(repo UserGetter, id int) { ... }

Почему так:

  • Минимальные интерфейсы: потребитель определяет только нужные ему методы, а не все методы реализации
  • Слабая связанность: пакет storage не знает о пакете service
  • Легкое тестирование: маленький интерфейс проще замокать
  • Принцип ISP (Interface Segregation Principle): много маленьких интерфейсов лучше одного большого

Исключение: стандартная библиотека определяет общепринятые интерфейсы (io.Reader, fmt.Stringer), потому что они используются повсеместно.

🧠Квиз 🏆Лидеры 🎯Собесед. 📖Вопросы 📚База зн.