Первый результат печатается как time to throw error и false; второй — как и false. Между парами будет пустая строка.
Поведение сравнения error с nil при возврате нулевого указателя
Первый результат печатается как time to throw error и false; второй — как <nil> и 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-интерфейса должны отсутствовать и динамический тип, и значение.