Поведение сравнения error с nil при возврате нулевого указателя

Первый результат печатается как time to throw error и false; второй — как <nil> и false. Между парами будет пустая строка.

Короткий ответ

Что ответить на собеседовании

Первый результат печатается как time to throw error и false; второй — как и false. Между парами будет пустая строка.

Подробный разбор

Ответ с пояснениями

Условие

Нужно исследовать, как работает функция, возвращающая значение типа error, и какие строки появятся в выводе при проверке результата на nil. Особое внимание следует уделить тому, что интерфейс error может хранить нулевой указатель конкретного типа (например, *os.PathError), что меняет результат сравнения с nil.

func someFunc(shouldReturnErr bool) error {
  var err *os.PathError = nil

  if shouldReturnErr {
    return errors.New("time to throw error")
  }

  return err
}

func main() {
  errTrue := someFunc(true)
  fmt.Println(errTrue)
  fmt.Println(errTrue == nil)

  fmt.Println()

  errFalse := someFunc(false)
  fmt.Println(errFalse)
  fmt.Println(errFalse == nil)
}

Проанализируйте, какие значения будет выводить программа в обоих случаях и почему сравнение с nil даёт ожидаемый или неожиданный результат.

Ответ

Первый результат печатается как time to throw error и false; второй — как и false. Между парами будет пустая строка.

someFunc(true) возвращает обычную ненулевую ошибку. В false-ветке возвращается error с динамическим типом *os.PathError и nil-указателем, поэтому сравнение с nil тоже ложно.

fmt отображает этот nil-указатель как <nil>, но внешний вид не означает пустой интерфейс. Нужно явно возвращать nil в ветке без ошибки. Наличие метода Error у конкретного типа не меняет правило: для nil-интерфейса должны отсутствовать и динамический тип, и значение.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее