🔴 Сложный · 3 очк. defer, panic, recover
В чем ловушка: func f() (err error) { if err := validate(); err != nil { return err }; return nil }?
A err в if - новая переменная (short declaration), затеняющая именованный возврат; если позже defer проверяет err, он увидит nil вместо ошибки
B Код не скомпилируется
C Ловушки нет, код работает корректно
D validate() вызовется дважды
Объяснение вопроса

Оператор := в коротком объявлении if создает новую переменную во внутренней области видимости, затеняя именованный возврат:

func saveFile(name string) (err error) {
    // defer, полагающийся на named return:
    defer func() {
        if err != nil {
            log.Printf("failed: %v", err)
        }
    }()

    // ЛОВУШКА: := создает НОВЫЙ err, затеняющий named return
    if err := os.WriteFile(name, data, 0644); err != nil {
        return err // возвращает ошибку, но...
    }
    // ...здесь named return err все еще nil!
    // defer увидит err == nil, даже если выше был return err

    return nil
}

// Решение: использовать = вместо :=
func saveFile(name string) (err error) {
    defer func() {
        if err != nil { log.Printf("failed: %v", err) }
    }()

    err = os.WriteFile(name, data, 0644) // = вместо :=
    if err != nil {
        return err
    }
    return nil
}

Линтер go vet с флагом -shadow и golangci-lint умеют обнаруживать такое затенение.

🧠Квиз 🏆Лидеры 🎯Собесед. 📖Вопросы 📚База зн.