Проверка рациональности интерфейса
Проверка соответствия интерфейса на этапе компиляции. Это включает в себя:
- Проверку экспортируемого типа, который реализует конкретный интерфейс в рамках API интерфейса
- Типы (как экспортируемые, так и неэкспортируемые), реализующие тот же интерфейс, принадлежат к коллекции реализующих типов
- Любые сценарии, нарушающие проверку рациональности интерфейса, приведут к остановке компиляции и уведомлению пользователя
Дополнение: Вышеперечисленные три пункта - это механизмы проверки интерфейса компилятора. Общая идея заключается в том, что ошибки при использовании интерфейса будут сообщаться на этапе компиляции. Поэтому этот механизм может быть использован для выявления некоторых проблем на этапе компиляции.
Не рекомендуемый подход:
// Если Handler не реализует http.Handler, произойдет ошибка во время выполнения
type Handler struct {
  // ...
}
func (h *Handler) ServeHTTP(
  w http.ResponseWriter,
  r *http.Request,
) {
  ...
}
Рекомендуемый подход:
type Handler struct {
  // ...
}
// Используется для запуска механизма проверки интерфейса на рациональность на этапе компиляции
// Если Handler не реализует http.Handler, произойдет ошибка на этапе компиляции
var _ http.Handler = (*Handler)(nil)
func (h *Handler) ServeHTTP(
  w http.ResponseWriter,
  r *http.Request,
) {
  // ...
}
Если *Handler не соответствует интерфейсу http.Handler, оператор var _ http.Handler = (*Handler)(nil) не будет компилироваться.
Справа от присваивания должно быть нулевое значение утвержденного типа. Для типов указателей (например, *Handler), срезов и карт это nil; для типов структур это пустая структура.
type LogHandler struct {
  h   http.Handler
  log *zap.Logger
}
var _ http.Handler = LogHandler{}
func (h LogHandler) ServeHTTP(
  w http.ResponseWriter,
  r *http.Request,
) {
  // ...
}