如何正确使用cockroachdb/errors处理第三方库错误避免重复堆栈
处理第三方库错误的解决方案
针对使用cockroachdb/errors时第三方库错误导致的重复堆栈问题,直接给你几个实用方案:
优先用
errors.WithMessage替代errors.Wraperrors.Wrap会强制添加新的堆栈跟踪,而WithMessage仅为错误添加上下文描述,不会新增堆栈。如果第三方库返回的错误已经包含堆栈(不管是不是用同个错误库生成的),用这个方法就不会出现重复堆栈的问题:func DoSomething() error { err := some.ThirdPartyLibraryCode(...) if err != nil { return errors.WithMessage(err, "something happened here in DoSomething") } return nil }按需判断是否添加堆栈
如果你需要确保错误一定有堆栈,但又不想重复添加,可以用errors.HasStack判断错误是否已包含堆栈,再决定用Wrap还是WithMessage:func DoSomething() error { err := some.ThirdPartyLibraryCode(...) if err != nil { if errors.HasStack(err) { return errors.WithMessage(err, "something happened here in DoSomething") } // 第三方错误无堆栈,用Wrap添加上下文和堆栈 return errors.Wrap(err, "something happened here in DoSomething") } return nil }使用
errors.WithStackOnce(版本支持时)
部分新版本的cockroachdb/errors提供了WithStackOnce函数,它会自动检查错误是否已有堆栈:如果没有就添加堆栈和上下文,如果已有则只添加上下文,一步到位避免重复:func DoSomething() error { err := some.ThirdPartyLibraryCode(...) if err != nil { return errors.WithStackOnce(err, "something happened here in DoSomething") } return nil }输出时过滤重复堆栈(补救方案)
如果已经出现重复堆栈的错误,输出时可以通过自定义格式化逻辑,只保留最外层或最内层的堆栈信息。比如用errors.GetAllStackTraces获取所有堆栈,然后选择需要的部分输出:func printError(err error) { stacks := errors.GetAllStackTraces(err) // 只打印第一个堆栈(最外层) if len(stacks) > 0 { fmt.Printf("stack trace:\n%s\n", stacks[0].String()) } // 打印错误信息 fmt.Printf("error: %v\n", err) }
核心思路就是:不要重复给已有堆栈的错误添加新堆栈,优先用仅添加上下文的方法,或让库自动判断是否需要添加堆栈。
内容的提问来源于stack exchange,提问作者HelloWorld
相关产品推荐
相关产品推荐

