-
-
Notifications
You must be signed in to change notification settings - Fork 6k
Closed as not planned
Description
Design
Let Must
functions handle all "internal server errors", let route handlers have return values.
The "panic/recover" is quite fast, not too much slower than "if err" check in real world, much faster than a DB query. And in most cases, the panic won't happen. The code just works as the "panic/recover" doesn't exist.
func Middleware(...) {
defer func() {
err := recover()
if err != nil {
// ErrNotExist renders 404 page, ErrPermissionDenied renders 403 page, etc, other errors render 500 page
RenderErrorPage(err)
}
}
}
func Handler(ctx *Context) Response {
user := MustOrNotExist(GetUserByID(uid))
issue := Must(GetIssueByID(issueID))
return RenderHTML(user, issue) // or RespondJSON(....)
}
func Must[T](...) T {
if err != nil {
panic(WrapMustError(err))
}
}
"panic" benchmark in real world
- "recover panic" catch: 140.5 ns/op
- "if err" check: 77.66 ns/op
func BenchmarkErrorPanic(b *testing.B) {
foo := func(i int) error {
return fmt.Errorf("err-%d", i)
}
handleErr := func(err error) {
_ = err
}
byPanic := func(i int) {
defer func() {
if err := recover().(error); err != nil {
handleErr(err)
}
}()
if err := foo(i); err != nil {
panic(err)
}
}
byIfErr := func(i int) {
err := foo(i)
if err != nil {
handleErr(err)
}
}
// BenchmarkErrorPanic/panic-12 8230132 140.5 ns/op
b.Run("panic", func(b *testing.B) {
for i := 0; i < b.N; i++ {
byPanic(i)
}
})
// BenchmarkErrorPanic/error-12 15548337 77.66 ns/op
b.Run("error", func(b *testing.B) {
for i := 0; i < b.N; i++ {
byIfErr(i)
}
})
}
lafriks6543
Metadata
Metadata
Assignees
Labels
No labels