If you have any questions or suggestions, please contact us in time. My official account is “Brain fried Fish”, GitHub address: github.com/eddycjy.

Some time ago, AFTER I shared the article “Sneak peek, The Struggle of Go2 Error”, I had an in-depth conversation with a friend. He shared with me the way their project team adjusted the Go Error handling.

To put it simply, use panic in business code to replace the “never-ending” if ERR! = nil. This is the focus of today’s article. Let’s take a look at how to do it and what the advantages and disadvantages are.

Why do you want to replace

In Go, if err! = nil (nil, nil);

err := foo() if err ! = nil { //do something.. return err } err := foo() if err ! = nil { //do something.. return err } err := foo() if err ! = nil { //do something.. return err } err := foo() if err ! = nil { //do something.. return err }Copy the code

The above is sample code, relatively straightforward. In engineering practice, you have to jump around and add if err to all packages! = nil, in general, it’s a little tedious to care about the whole upstream and downstream. I don’t need to go into more details. Check out my previous post.

How to replace err! = nil

I don’t want to write if err! = nil code, and one way to do that is to replace it with panic. Example code is as follows:

func GetFish(db *sql.DB, name string) []string { rows, err := db.Query("select name from users where `name` = ?" , name) if err ! = nil { panic(err) } defer rows.Close() var names []string for rows.Next() { var name string err := rows.Scan(&name) if err ! = nil { panic(err) } names = append(names, name) } err = rows.Err() if err ! = nil { panic(err) } return names }Copy the code

In the above business code, we replace the function return of err by panic, so naturally the downstream business code associated with it does not need to write if err! = nil code:

Func main() {fish1 := fish2 (db, "fish2 ") fish2 := fish2 (db," fish2 ") fish3 := fish2 (db, "fish2 ") fish3 := fish3 (db," fish2 ")... }Copy the code

Also, after switching to the error mechanism using Panic mode, we have to add the Recover method to the outer layer:

func AppRecovery() gin.HandlerFunc { return func(c *gin.Context) { defer func() { if err := recover(); err ! = nil { if _, ok := err.(AppErr); ok { // do something... } else { panic(err) } } }() } }Copy the code

After each panic, an assertion is made based on the errors it throws to identify whether the AppErr error type is customized. If so, a series of processing actions can be performed. Otherwise, proceed up panic to the top-level Recovery method for processing.

This is a relatively complete panic link handling.

The advantages and disadvantages

  • In terms of advantages:

    • The overall code structure looks much cleaner and just focuses on the implementation logic.

    • No need to focus and write verbose if err! = nil error handling code.

  • In terms of disadvantages:

    • The increased cognitive burden requires every new and old student in the program to be aware of the model and to do a basic specification or training.

    • There is a performance overhead, as there is a user-mode context switch every time Panic occurs.

    • There are certain risks, once panic is not recovered, it will lead to accidents.

    • It is not officially recommended by Go, which is contrary to the definition of panic itself, i.e. confusion of the concepts of panic and error.

conclusion

In today’s article, I shared with you how to use panic to deal with Go errors. It must have advantages and disadvantages, and a balance needs to be made.

Did your team make any new adjustments to Go error handling? Welcome to exchange and share in the comments area.

My official account

Share Go language, micro service architecture and strange system design, welcome to pay attention to my public number and I exchange and communication.

The best relationship is mutual achievement. Your praise is the biggest motivation for the creation of fried fish. Thank you for your support.