Почему интерфейс с nil-указателем внутри не равен nil?
- Почему функция вернула error, который не nil, хотя внутри nil?
Интерфейсное значение — пара (тип, значение). Оно равно nil, только когда обе части nil. Если положить в интерфейс nil-указатель конкретного типа, тип уже заполнен — интерфейс не nil, и err != nil срабатывает.
- Классика: функция возвращает *MyError, равный nil, через тип error
- Правило: возвращать именно nil, а не типизированный nil-указатель
- Посмотреть пару — fmt.Printf("%T %v", err, err)
А ещё Метод на nil-указателе можно вызвать — если он не обращается к полям
Подробно
Почему так. Сравнение интерфейса с 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.
- Как избежать.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✓Интерфейс — пара (тип, значение); nil, только если обе nil
- ✗Интерфейс с nil-указателем внутри всегда равен nil, просто == сравнивает адреса
- ✗Это ошибка компилятора
- ✗Возвращать типизированный nil-указатель через error — идиоматично
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.