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
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)
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
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
}
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()
}
func ff() {
panic("panic in ff")
}