I'm writing my web application with Go. I want to convert most of the errors from API to panics, and then catch those panics in higher-level function, log them and return error page to user.
Something like this:
func Handler(body func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
return func(responseWriter http.ResponseWriter, request *http.Request) {
defer recoverIfPanic(responseWriter, request)
body(responseWriter, request)
}
}
func recoverIfPanic(responseWriter http.ResponseWriter, request *http.Request) {
reason := recover()
if reason == nil {
return
}
// log and return http error
}
func PanicIf(err error, httpStatus int, description string) {
if error != nil {
panic(MyPanicStruct{err: err, httpStatus: httpStatus, description: description})
}
}
and in my actual code
result, err := SomeApi(...)
PanicIf(err, http.StatusInternalServerError, "SomeApi")
In 99% cases I can't do anything reasonable when, e.g. SQL server returns unexpected error or file is missing from filesystem, all I want is to log this situation and return error to user. So I can't see any reason I should return "err" unwinding stack manually, actually I'll lost stacktrace and context and it would be more difficult to find error reason.
Is there anything I miss so this approach won't work well? It seems that most Go articles recommend against using panic/recover, but I don't see why. It looks exactly like good old throw-catch mechanism in Java (and similar languages) and it works perfectly for web applications.