序
本文次要钻研一下 golang 的 error 加强
Errors in Go 1.13
golang 的 1.13 版本对 error 进行了加强,次要是
- 引入了 Unwrap 办法
- 减少 Is 和 As 办法
- fmt.Errorf 反对
%w
来包装 error
实例
package main
import (
"errors"
"fmt"
"os"
)
var DemoErr = errors.New("test error stack")
// https://itnext.io/golang-error-handling-best-practice-a36f47b0b94c
func main() {if err := methodA(false); err != nil {fmt.Printf("%+v\n", err)
}
if err := methodA(true); err != nil {fmt.Printf("%+v\n", err)
fmt.Printf("%+v\n", errors.Unwrap(err))
fmt.Printf("%+v\n", errors.Unwrap(errors.Unwrap(err)))
fmt.Println("errors.Is(err, DemoErr)=", errors.Is(err, DemoErr))
fmt.Println("errors.As(err, &DemoErr)=", errors.As(err, &DemoErr))
var pe *os.PathError
fmt.Println("errors.Is(err, pe)=", errors.Is(err, pe))
fmt.Println("errors.As(err, &pe)=", errors.As(err, &pe))
}
}
func methodA(wrap bool) error {if err := methodB(wrap); err != nil {
if wrap {return fmt.Errorf("methodA call methodB error: %w", err)
}
return err
}
return nil
}
func methodB(wrap bool) error {if err := methodC(); err != nil {
if wrap {return fmt.Errorf("methodB call methodC error: %w", err)
}
return err
}
return nil
}
func methodC() error {return DemoErr}
输入
test error stack
methodA call methodB error: methodB call methodC error: test error stack
methodB call methodC error: test error stack
test error stack
errors.Is(err, DemoErr)= true
errors.As(err, &DemoErr)= true
errors.Is(err, pe)= false
errors.As(err, &pe)= false
小结
- wrap 对 error 进行了包装,不过没有蕴含堆栈
- Is 会挨个 unwrap 去对 error 进行判断
errors.Is function behaves like a comparison to a sentinel error
- As 相似类型断言
errors.As function behaves like a type assertion
doc
- Errors
- Working with Errors in Go 1.13
- Error Handling in Go 1.13
- Proposal: Go 2 Error Inspection
- Golang error 浅析