Go: почему err == nil может вернуть false, хотя ошибки нет 🛑
Представим обычную функцию, которая возвращает ошибку:
func doSomething() error { var err *MyError = nil return err }
На первый взгляд всё нормально: err равен nil, значит, ошибки нет.
Но проверим:
func main() { err := doSomething() fmt.Println(err == nil) // false }
Неожиданно? Причина в том, как го работает с интерфейсами. Что здесь происходит?
type MyError struct{} func (e *MyError) Error() string { return "something went wrong" }
Тип *MyError реализует интерфейс error.
Когда функция возвращает типизированный nil-указатель как error, интерфейс получает динамический тип *MyError и значение nil.
Условно это выглядит так:
error ├── dynamic type: *MyError └── dynamic value: nil
Сам интерфейс уже не равен nil, потому что в нём сохранена информация о типе. Как правильно?
Если ошибки нет, возвращаем обычный nil: func doSomething() error { // Выполняем работу return nil }
Или, если ошибка возникает при определённых условиях:
func doSomething() error { var err *MyError if someCondition { err = &MyError{} } if err != nil { return err } return nil }
Вывод: если функция возвращает интерфейс error, не стоит без необходимости возвращать из неё типизированный nil-указатель.
Это небольшой нюанс, который легко пропустить при работе с собственными типами ошибок и интерфейсами.