20230224日志

20230224日志

2023年2月24日
2023
202302, go, defer

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(), 让维护者看懂忽略错误是有意为之