Как правильно сравнивать error с nil в Go

Программа напечатает oops. При i=4 err внутри foo равен nil как *MyError, но возврат упаковывает его в интерфейс error с ненулевым динамическим типом.

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

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

Программа напечатает oops. При i=4 err внутри foo равен nil как *MyError, но возврат упаковывает его в интерфейс error с ненулевым динамическим типом.

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

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

Условие

Определите, какой вывод будет у следующей программы при её запуске.

package main

import "fmt"

type MyError struct {
 data string
}

func (e *MyError) Error() string {
 return e.data
}

func main() {
 err := foo(4)
 if err != nil {
  fmt.Println("oops")
 } else {
  fmt.Println("ok")
 }
}

func foo(i int) error {
 var err *MyError
 if i > 5 {
  err = &MyError{data: "i > 5"}
 }
 return err
}

Ответ

Программа напечатает oops. При i=4 err внутри foo равен nil как *MyError, но возврат упаковывает его в интерфейс error с ненулевым динамическим типом.

Проверка err!=nil поэтому истинна. Метод Error не вызывается: main печатает только строку oops, так что разыменования nil здесь нет. Исправьте foo: if i > 5 { return &MyError{data: "i > 5"} }; return nil. Альтернатива — объявить локальную переменную именно типа error и оставлять её nil при успехе.

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

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

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

Подробнее