Save 37% off PRO during our Black Friday Sale! »

Go1.13以後のエラーハンドリングについて語ろう / Let's talk about error handling after Go 1 13

05b6e6c70a424bb99adffb797ef45042?s=47 Koya IWAMURA
October 28, 2019

Go1.13以後のエラーハンドリングについて語ろう / Let's talk about error handling after Go 1 13

05b6e6c70a424bb99adffb797ef45042?s=128

Koya IWAMURA

October 28, 2019
Tweet

Transcript

  1. Go1.13 以後の エラーハンドリング について語ろう Go Conference 2019 Autumn, Oct 28

    2019 Koya IWAMURA CyberAgent, Inc. @cia_rana
  2. Go1.13 からスタックトレースをとるための機能が追加 • fmt.Errorf (%w) • errors.Is • errors.As •

    errors.Unwrap
  3. fmt.Errorf (%w) • 既存のエラーをラッピング • 情報を付加 func MyFunc() error {

    err := f() return fmt.Errorf(“MyFunc: %w”, err) }
  4. errors.Is • 値の比較 if err == sql.ErrNoRows { fmt.Println(err) }

    if errors.Is(err, sql.ErrNoRows) { fmt.Println(err) } Go1.13〜
  5. errors.As • 型の比較(assertion, switch)、キャプチャ if e, ok := err.(*url.Error); ok

    { fmt.Printf(“isTimeout: %v”, e.Timeout()) } var e *url.Error if errors.As(err, &e) { fmt.Printf(“isTimeout: %v”, e.Timeout()) } Go1.13〜
  6. Go1.13以後 エラーハンドリングする上での留意点

  7. 01 `if err != nil` が 無力化される Go1.13以後 エラーハンドリングする上での留意点

  8. `if err != nil` が無力化される func f() ([]byte, error) {

    resp, err := http.Get("cyberagent.ai") if err != nil { return nil, err } return ioutil.ReadAll(resp.Body) } func main() { a, err := f() if err != nil { fmt.Println(err) } fmt.Println(string(a)) }
  9. `if err != nil` が無力化される func f() ([]byte, error) {

    resp, err := http.Get("cyberagent.ai") if err != nil { return nil, err } a, err := ioutil.ReadAll(resp.Body) return a, fmt.Errorf(“%w”, err) } func main() { a, err := f() if err != nil { fmt.Println(err) } fmt.Println(string(a)) }
  10. `if err != nil` が無力化される func f() ([]byte, error) {

    resp, err := http.Get("cyberagent.ai") if err != nil { return nil, err } a, err := ioutil.ReadAll(resp.Body) return a, fmt.Errorf(“%w”, err) } func main() { a, err := f() if err != nil { fmt.Println(err) } fmt.Println(string(a)) } errがnilでも・・・
  11. `if err != nil` が無力化される func f() ([]byte, error) {

    resp, err := http.Get("cyberagent.ai") if err != nil { return nil, err } a, err := ioutil.ReadAll(resp.Body) return a, fmt.Errorf(“%w”, err) } func main() { a, err := f() if err != nil { fmt.Println(err) } fmt.Println(string(a)) } errがnilでも・・・ if文の中が走っちゃう
  12. `if err != nil` が無力化される func f() ([]byte, error) {

    resp, err := http.Get("cyberagent.ai") if err != nil { return nil, err } a, err := ioutil.ReadAll(resp.Body) return a, fmt.Errorf(“%w”, err) } func main() { a, err := f() if errors.Is(err, nil) { fmt.Println(err) } fmt.Println(string(a)) } errors.Isを使おう!
  13. 02 xerrorsと同じ挙動に 見せかけて実は違う Go1.13以後 エラーハンドリングする上での留意点

  14. xerrorsと同じ挙動に見せかけて実は違う https://github.com/golang/go/wiki/ErrorValueFAQ

  15. xerrorsと同じ挙動に見せかけて実は違う xerrors.Errorfでは ラップした位置に関する情報をとれる

  16. xerrorsと同じ挙動に見せかけて実は違う fmt.Errorf では ラップした位置に関する情報をとれない

  17. xerrorsと同じ挙動に見せかけて実は違う xerrors.Errorf で error をラップするには フォーマット指示子を ”: %w” にして 末尾に持ってこなくてはならない

    xerrors.Errorf(“MyError: %w”, err)
  18. xerrorsと同じ挙動に見せかけて実は違う fmt.Errorf で error をラップするには フォーマット指示子が ”%w” でありさえすれば良い fmt.Errorf(“MyError: %w

    in main.main”, err)
  19. Thank you for listening!