Last active
October 13, 2020 09:19
-
-
Save tkm-kj/6d31ab29e2dee57fd2bf5bb20953bf6c to your computer and use it in GitHub Desktop.
errors.Wrap のstacktraceの出方とエラー判定の方法
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"log" | |
"github.com/pkg/errors" | |
) | |
var ( | |
Err1 = errors.New("err1") | |
Err2 = errors.New("err2") | |
Err3 = errors.New("err3") | |
Err4 = errors.New("err4") | |
) | |
func func1() error { | |
return Err1 | |
} | |
func func2() error { | |
return errors.Wrap(Err2, "error happened on func2") | |
} | |
func func3() error { | |
err := func4() | |
if err != nil { | |
return errors.Wrap(err, "func3 catch error") | |
} | |
return nil | |
} | |
func func4() error { | |
return Err3 | |
} | |
func func5() error { | |
err := func6() | |
if err != nil { | |
return errors.Wrap(err, "func5 catch error") | |
} | |
return nil | |
} | |
func func6() error { | |
return errors.Wrap(Err4, "error happened on func6") | |
} | |
func func7() error { | |
err := func6() | |
if err != nil { | |
return err | |
} | |
return nil | |
} | |
func main() { | |
err := func1() | |
if err != nil { | |
// Wrap せずに返す | |
// エラーが定義されている行数だけ出てくる | |
// 直接的にエラーが return されたところがわからない | |
// なので、あまり役に立たない | |
log.Printf("%+v", err) | |
fmt.Println() | |
// スタンダードなエラーはそのまま err を switch 文に渡せる | |
switch err { | |
case Err1: | |
log.Println("Err1発生したよ") | |
} | |
} | |
fmt.Println() | |
fmt.Println() | |
fmt.Println() | |
err = func2() | |
if err != nil { | |
// 大元でWrap | |
// エラーが返された行数まではっきりわかる | |
log.Printf("%+v", err) | |
fmt.Println() | |
// Wrapした時点で通常の err だけ渡して switch しても期待通りに動かない | |
switch err { | |
case Err2: | |
log.Println("Err2発生したよ") | |
} | |
fmt.Println() | |
// Wrap したやつは Cause を使うと取り出せるので、それで分岐させる | |
switch errors.Cause(err) { | |
case Err2: | |
log.Println("Err2発生したよその2") | |
} | |
} | |
fmt.Println() | |
fmt.Println() | |
fmt.Println() | |
err = func3() | |
if err != nil { | |
// func3だけWrap | |
// Wrapされたところからstacktraceが生まれる | |
// func4で大元のエラーが発生しているが、その情報がエラーに入っていない | |
// errorの途中からWrapしてもあまりありがたみがないことがわかった | |
log.Printf("%+v", err) | |
} | |
fmt.Println() | |
fmt.Println() | |
fmt.Println() | |
err = func5() | |
if err != nil { | |
// 2重にWrap | |
// エラーの大元(func6)の情報からstacktraceに入ってくる。また、func5の発生場所もはっきりわかる。ぶっちゃけ全部Wrapしちゃう方式でも問題ない気がする | |
log.Printf("%+v", err) | |
fmt.Println() | |
// 2重にWrapしていても、大元だけチェックすれば良い | |
switch errors.Cause(err) { | |
case Err4: | |
log.Println("Err4発生したよ") | |
} | |
} | |
fmt.Println() | |
fmt.Println() | |
fmt.Println() | |
err = func7() | |
if err != nil { | |
// エラーの大元だけWrapして子供は return で流す。 | |
// func5の時と同じ。大元だけWrapして後は全部 return で流すのが一番丁度よい。 | |
log.Printf("%+v", err) | |
fmt.Println() | |
switch errors.Cause(err) { | |
case Err4: | |
log.Println("Err4発生したよその2") | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment