去哪里记录错误

Ale*_*ker 2 error-handling logging error-logging go

也许这是一种意见,或者它实际上是一种最佳实践,但我想要正确地做到这一点.

请考虑以下代码:

func main() {
    if err := doSomething(); err != nil {
        // log here and exit?
    }
}

func doSomething() {
    f, err := os.Open("filename.ext")
    if err != nil {
        // log here and return the error/exit?
    }
}
Run Code Online (Sandbox Code Playgroud)

我很想知道应该记录错误的位置以及退出程序的位置(假设恢复是不可能的).一些可能性包括:在被调用者中记录和退出; 登录被调用者,返回错误,并退出调用者; 登录被叫方,返回错误,登录调用方并退出.所有这些方法似乎都有好处.例如,第二种方法允许细粒度的错误消息,但仍然将错误传递给调用者.但是,它将导致两条日志消息.

谢谢!

cap*_*aig 5

这是一个有趣的话题,真的归结为很多意见,所以这可能会被关闭.我尝试遵循一些指导原则:

  1. 只能"处理"一次错误.记录计为处理.如果您不知道需要采取什么行动,请将其传递出去.您绝对不希望每次出现多次记录错误.

  2. 如果您的调用者可能因错误而改变其行为,则应将其返回.如果你仍然可以做错"你的"工作",也许你应该记录并继续.

  3. 有时,将错误添加到错误最初进入系统的位置会有所帮助(因此日志行可以包含错误来自的位置,而不仅仅是最终记录的位置).像https://github.com/pkg/errors这样的东西对此很有用.

  • 为了进一步增加这一点,通常不要在`main()`函数中使用`os.Exit()`.主要原因是,与`panic()`不同,`os.Exit()`无法被捕获,并且`main()`确实应该具有进程终止时的权限以及如何.作为推论,`os.Exit()`和扩展名,`log.Fatal()`(调用`os.Exit()`)应该**_绝对不会_**用于其他人想要导入的库中(我认为这是_ALL_时间,这是一种非常糟糕的做法).如果它是致命的(在可导入的包中),`panic()`,不要`os.Exit()`或`log.Fatal()`. (3认同)