func f() (err error) { if err := validate(); err != nil { return err }; return nil }?Оператор := в коротком объявлении 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 умеют обнаруживать такое затенение.