Go: terugkeer van uitstel

Ik wil een fout van een functie retourneren als deze in paniek raakt (in Go):

func getReport(filename string) (rep report, err error) {
    rep.data = make(map[string]float64)
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered in f", r)
            err, _ = r.(error)
            return nil, err
        }
    }()
    panic("Report format not recognized.")
    // rest of the getReport function, which can try to out-of-bound-access a slice
    ...
} 

Ik schijn het concept van paniek en uitstel verkeerd te hebben begrepen. Kan iemand mij informeren?


Antwoord 1, autoriteit 100%

In een uitgestelde functie kunt u de geretourneerde parameters wijzigen, maar u kunt geen nieuwe set retourneren. Dus een simpele verandering in wat je hebt zal het laten werken.

Er is nog een probleem met wat je schreef, namelijk dat je in paniek raakte met een stringmaar een errorverwacht in je typebewering.

Hier is een oplossing voor beide (Play)

defer func() {
    if r := recover(); r != nil {
        fmt.Println("Recovered in f", r)
        // find out exactly what the error was and set err
        switch x := r.(type) {
        case string:
            err = errors.New(x)
        case error:
            err = x
        default:
            err = errors.New("Unknown panic")
        }
        // invalidate rep
        rep = nil
        // return the modified err and rep
    }
}()

Antwoord 2, autoriteit 8%

kijk hier eens naar

package main
import "fmt"
func iWillPanic() {
    panic("ops, panic")
}
func runner() (rtnValue string) {
    rtnValue := ""
    defer func() {
        if r := recover(); r != nil {
            // and your logs or something here, log nothing with panic is not a good idea
            rtnValue = "don't panic" // modify the return value, and it will return
        }
    }()
    iWillPanic()
    return rtnValue
}
func main() {
    fmt.Println("Return Value:", runner())
}

Antwoord 3, autoriteit 4%

func TestReturnFromPanic(t *testing.T) {
   fn := func(filename string) (rep string, err error) {
       defer func() {
           if r := recover(); r != nil {
               err = fmt.Errorf("panic in getReport %s", r)
           }
       }()
       return filename[100:], nil
   }
   t.Log(fn(``))
}

De benoemde retourparameter erris de truc.

https://play.golang.org/p/jpaCa9j2iAf

Other episodes