20230224日志
2023年2月24日
go #
err总是通过最后一个返回值返回
panicking #
panic可以被recover恢复, recover仅可以在defer中, 即使发生panic,defer也会执行
节省的使用panic, 在programmer error或者dependency场景中使用
func main(){
defer fun(){
if f := recevoer(); r != nil {
fmt.Println("recover", r)
}
}()
f()
}
func f(){
fmt.Println("a")
panic("foo")
fmt.Println("b")
}
ignoring when to wrap an error #
需要添加额外信息;把error作为特定的一种error
老式的方式,通过struct包装
type BarError struct {
Err error
}
func (b BarError) Error() string {
return "bar failed:" + b.Err.Error()
}
通过%w添加上下文, 可以unwrap
if err != nil {
return fmt.Errorf("bar failed: %w", err)
}
通过%v添加上下文, 不可以unwrap
if err != nil {
return fmt.Errorf("bar failed: %v", err)
}
checking an error type inaccurately #
errors.As. This function recursively unwraps an error and returns true if an error in the chain matches the expected type
func handler(w http.ResponseWriter, r *http.Request) {
// Get transaction ID
amount, err := getTransactionAmount(transactionID)
if err != nil {
if errors.As(err, &transientError{}) {
http.Error(w, err.Error(),
http.StatusServiceUnavailable)
} else {
http.Error(w, err.Error(),
http.StatusBadRequest)
}
return
}
// Write response
}
checking an error value inaccurately #
Expected errors should be designed as error values (sentinel errors): var ErrFoo = errors.New("foo")
Unexpected errors should be designed as error types: type BarError struct { … }
, with BarError implementing the error interface
errors.Is 处理wraped的err value的比较
err := query()
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
// ...
} else {
// ...
}
}
handling an error twice #
Logging an error is handling an error, and so is returning an error. Hence, we should either log or return an error, never both
not handling an error #
func notify() error {
// ...
}
必须这样忽略错误 _ = notify()
, 让维护者看懂忽略错误是有意为之