Получить доступ

Почему интерфейс с nil-указателем внутри не равен nil?

MiddleМетоды и интерфейсы
Ещё спрашивают так:
  • Почему функция вернула error, который не nil, хотя внутри nil?
Коротко

Интерфейсное значение — пара (тип, значение). Оно равно nil, только когда обе части nil. Если положить в интерфейс nil-указатель конкретного типа, тип уже заполнен — интерфейс не nil, и err != nil срабатывает.

  • Классика: функция возвращает *MyError, равный nil, через тип error
  • Правило: возвращать именно nil, а не типизированный nil-указатель
  • Посмотреть пару — fmt.Printf("%T %v", err, err)

А ещё Метод на nil-указателе можно вызвать — если он не обращается к полям

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Почему так. Сравнение интерфейса с nil проверяет, что в нём нет ни типа, ни значения. Присваивание var err error = (*MyErr)(nil) записывает тип *MyErr — интерфейс «знает», что внутри указатель на MyErr, просто этот указатель пустой.

Где встречается: функции, возвращающие конкретный тип ошибки через промежуточную переменную; фабрики, возвращающие интерфейс и nil-указатель реализации; поля-интерфейсы, заполненные из nil-указателей.

Как избегать: возвращать nil литералом; объявлять результат функции интерфейсом error с самого начала; линтеры (nilness, staticcheck) ловят часть случаев.

Пример

type MyErr struct{}
func (*MyErr) Error() string { return "ошибка" }

func check(ok bool) error {
    var e *MyErr          // nil-указатель
    if !ok { e = &MyErr{} }
    return e              // интерфейс (тип *MyErr, значение nil) — не nil!
}

fmt.Println(check(true) == nil)   // false

// правильно
func check2(ok bool) error {
    if !ok { return &MyErr{} }
    return nil
}

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

  • Устройство интерфейса как пары.
  • Пример с error.
  • Как избежать.

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

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем