golang error and exception handling

Error (error)

  • error is an interface
    • We can define your own type of error to achieve this interface
type error interface {
	Error() string
}
  • Custom Error value should be defined unified group, rather than scattered in all corners of distribution
    • Then directly back these new variables return
// file error objectvar 
var (
        ErrEof = errors.New("EOF")
        ErrClosedPipe = errors.New("io: read/write on closed pipe")
)
// 多层包装错误
f() {
	if err := ff(); err != nil {
		return fmt.Errorf("f: %w", err)
	}	
}

// 解析错误
	err = errors.Unwrap(err)
  • Unified error handling
func logPanics(f http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		defer func() {
			if err := recover(); err != nil {
				log.Printf("[%v] caught panic: %v", r.RemoteAddr, err)
			}
			f(w, r)
		}()
	}
}

//使用
http.HandleFunc("/<path>", logPanics(func1))

Abnormal (panic)

  • Abnormal recovery (recover) must be written in defer function
    • Otherwise returned directly nil, and does not catch the exception
  • A child panic occurred goroutine will lead to the collapse of the entire program
    • An exception occurred can only be restored yourself goroutine
    • Every possible panic of goroutine should add an exception recovery process
  • panic indicates a serious error has occurred, should not be used frequently
    • But sometimes by panic simplify error handling
      Here Insert Picture Description
// 使用error的写法
func first() error {return nil}
func second() error {return nil}
func third() error {return nil}

func Do() error {
    var err error
    if err = first(); err == nil {
        if err = second(); err == nil {
            if err = third(); err == nil {
               return nil
            }
        }
    }
    return err
}

// 改为panic的写法

func Do2() (err error) {
    defer func(){
        if r:= recover() ; r!= nil{
            err = fmt.Errorf("Error: %+v", r)
        }
    }()
    first2()
    second2()
    third2()
    return
}
  • recover only take effect in the defer and defer must be registered before the panic
  • If you want to capture the underlying function of panic in the upper function, you must defer register (define) before the underlying function call
func f() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
		}
	}()

	// 注意ff调用必须在defer之后
	ff()
}

func ff() {
	panic("panic in ff")

}
Published 161 original articles · won praise 19 · views 50000 +

Guess you like

Origin blog.csdn.net/winter_wu_1998/article/details/101670307