Gin: Abort vs panic

Created on 14 Jun 2015  路  3Comments  路  Source: gin-gonic/gin

every time I want to return the error, i must write the following code

if err != nil {
    c.AbortWithError(code, err)
    return
}

it's ugly with so many return

I think using the panic maybe the best practice. Like Java's throw Exception

if err != nil {
    panic(err) // maybe err is ErrUserNotFound
}

err is defined as

type HTTPError interface {
    HTTPStatus() int
}

using the catchError middleware to catch the error and abort with the HTTPStatus

func catchError() gin.HandlerFunc {
    return func(c *gin.Context) {
        defer func() {
            if err := recover(); err != nil {
                switch err.(type) {
                case HTTPError:
                    e := err.(*errors.Error)
                    c.JSON(e.HTTPStatus(), e)
                    c.Abort()
                default:
                    c.AbortWithStatus(http.StatusInternalServerError)
                }
            }
        }()
        c.Next()
    }
}

lot's of ugly return are removed

bug wontfix

Most helpful comment

Tip: refactor your code into smaller functions, so instead of repeating:

if err != nil {
    c.AbortWithStatus(code, error)
    return 
}

you do:

func dosomething() error {
    err = dosomething1()
    if err != nil {
        return err
    }
    err = dosomething2()
    if err != nil {
        return err
    }
    err = dosomething3()
    if err != nil {
        return err
    }
}

func handler(c *gin.Context) {
    err := dosomething()
    if err != nil {
        c.AbortWithStatus(400, err)
        return;
    }
    // ...
}

All 3 comments

@lilee currently the best practice is to do:

AbortWithError()
return;

and then a middleware reads c.Errors in order to do something with the errors.

Using a panic() is a bad idea:

  • It is not Go idiomatic. In Go, a panic() is a strict exception (or an assertion). i.e. something really bad (probably a bug) happened.
  • Calling panic() is slow
  • When panic() is called, most of the middlewares will not work correctly, since a panic() usually means 500.
  • Debugging: you will not be able to differentiate between real crashes (like access no nil) and errors.

Of course, you are free to use whatever you want, but using panic() to control logic normal flow is a anti-pattern in Go.

Tip: refactor your code into smaller functions, so instead of repeating:

if err != nil {
    c.AbortWithStatus(code, error)
    return 
}

you do:

func dosomething() error {
    err = dosomething1()
    if err != nil {
        return err
    }
    err = dosomething2()
    if err != nil {
        return err
    }
    err = dosomething3()
    if err != nil {
        return err
    }
}

func handler(c *gin.Context) {
    err := dosomething()
    if err != nil {
        c.AbortWithStatus(400, err)
        return;
    }
    // ...
}

Thanks for explaination

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghost picture ghost  路  3Comments

rawoke083 picture rawoke083  路  3Comments

nxvl picture nxvl  路  3Comments

xpbliss picture xpbliss  路  3Comments

iiinsomnia picture iiinsomnia  路  3Comments