我正在开发一个CLI工具,在出现问题的情况下,我希望记录自定义错误,并带着恐慌退出。死机的问题是,panic退出之后是堆栈跟踪,我不想向用户显示它。有没有一种方法可以让你惊慌失措,拥有一个忍者般的隐秘/安静的出口?
(选择panic而不是os.Exit(),因为它可以处理任何defer,而且看起来干净多了。)
发布于 2020-07-20 02:24:59
嗯,一个直接的答案是肯定的,有一种方法:
如果出现自定义" sentinel“类型的错误,或者带有自定义的" sentinel”值,则
main中有一个defer-red调用,该调用recover()-s死机并检查返回的值是否为sentinel类型(或等于sentinel值-具体方法由您决定)。如果它检测到“已知”错误,它将静默退出,并返回非零退出代码;否则,它将再次panics。
但老实说,我认为你的心态太受编程语言的影响了,但也有例外:我还没有看到一个CLI应用程序在“通常的方式”处理错误时会有任何困难,或者实际上可以从使用panic中受益。
与您渴望的方法相反的一个论点是:冒泡错误允许在展开的调用堆栈的每个级别上向其添加更多上下文,这是有意义的,-producing尽可能有用地显示错误。基本上,它是这样工作的:
func main() {
...
err := DoStuff()
if err != nil {
log.Fatal("failed to do stuff: ", err)
}
...
}
func DoStuff() error {
foo, err := InitializeWhatever()
if err != nil {
return fmt.Errorf("failed to inialize whatever: %w", err)
}
...
return nil
}
func InitializeWhatever() (*Whatever, error) {
handle, err := OpenWhateverElse()
if err != nil {
return nil, fmt.Errorf("failed to open whatever else: %w", err)
}
...
return whatever, nil
}…它会产生类似这样的结果
failed to do stuff: failed to inialize whatever: failed to open whatever else: task failed successfully
…这清楚地表明了是哪一系列事件导致了不希望看到的结果。
当然,和往常一样,YMMV,除了你之外,没有人最了解你的情况,但它仍然是值得思考的事情。
这里是我在上面写的各种想法的列表。
net/http.ErrAbortHandler。用于使用这种方法来打破多个嵌套循环的encoding/json包(自那以后已经被修改,一些专家consider sentinel errors to be bad design并建议改为断言(使用Go的类型断言)错误的行为-例如,您可以查看net.Error如何具有Timeout和Temporary方法,这些方法允许暂时错误和由于超时而导致的错误及其组合没有具体的导出类型。相反,-but让它们都支持一组通用的方法,这些方法允许调用者理解错误的nature.
嗯,我推荐阅读this,因为我必须承认,如果你已经这样做了,你很可能一开始就不会问你的问题;-)
https://stackoverflow.com/questions/62983700
复制相似问题