ChatGPT解决这个技术问题 Extra ChatGPT

恐慌与 log.Fatalln() 的结果有何不同?

go

log.Fatalln() 上的文档:

func Fatalln(v ...interface{}) Fatalln 等价于 Println(),然后调用 os.Exit(1)。

Fatalln 的 source code

   310  // Fatalln is equivalent to Println() followed by a call to os.Exit(1).
   311  func Fatalln(v ...interface{}) {
   312      std.Output(2, fmt.Sprintln(v...))
   313      os.Exit(1)
   314  }

似乎主要区别在于错误是否可恢复(因为您可以恢复恐慌) - 这些之间有什么更显着的不同吗?

Panic 的界面 definition 是:

   215  // The panic built-in function stops normal execution of the current
   216  // goroutine. When a function F calls panic, normal execution of F stops
   217  // immediately. Any functions whose execution was deferred by F are run in
   218  // the usual way, and then F returns to its caller. To the caller G, the
   219  // invocation of F then behaves like a call to panic, terminating G's
   220  // execution and running any deferred functions. This continues until all
   221  // functions in the executing goroutine have stopped, in reverse order. At
   222  // that point, the program is terminated and the error condition is reported,
   223  // including the value of the argument to panic. This termination sequence
   224  // is called panicking and can be controlled by the built-in function
   225  // recover.
   226  func panic(v interface{})

看起来恐慌没有返回任何东西。

这是主要区别吗?否则,假设恐慌没有恢复,它们似乎在应用程序中执行相同的功能。

考虑阅读 official go blog,其中恐慌 &恢复得到很好的解释
一个普遍的观点是,你不应该使用任何一个。 dave.cheney.net/2015/11/05/lets-talk-about-logging
在阅读了 Go 博客之后,Panic 的行为似乎有点像异常,它会在执行堆栈中冒泡,直到被 Recover 捕获。一般来说,除非你也实现了 Recover,否则不要惊慌。永远不要在图书馆登录。致命的。根据情况总是返回 nil、false 或错误
@francojposa 对。正如评论所说:这篇文章既不使用也不使用。
@francojposa:如果您认为帖子中的信息不正确,我鼓励您告诉作者。戴夫非常风度翩翩。他所说的关于围棋的大部分内容很快就变成了“普遍观点”,如果它还没有的话。

J
JimB

日志消息会发送到配置的日志输出,而 panic 只会写入 stderr。

恐慌将打印一个堆栈跟踪,这可能与错误根本无关。

当程序 panic 时会执行 defers,但调用 os.Exit 会立即退出,并且无法运行 deferred 函数。

通常,仅将 panic 用于编程错误,其中堆栈跟踪对于错误的上下文很重要。如果消息不是针对程序员的,那么您只是将消息隐藏在多余的数据中。


所以在测试的背景下,恐慌似乎会更好?因为他们是针对程序员的..
@enderland:只有在堆栈跟踪相关时才会恐慌(我知道在测试时我不想要无用的堆栈跟踪,当关于失败的简单消息就足够了)。如果您只需要编写错误消息,那么只需编写该消息即可。 (另外,尽可能使用 t.Fatal/t.Fatalf vs log in 测试)
Fatal 不执行延迟的事实是 IMO 的一个大问题,我看不出这如何使其成为可行的解决方案。例如,因为我的程序不会清理它的临时目录......
如果处理临时目录的函数返回错误,则将调用 defer 并由调用者负责决定是否需要 log.Fatal。也许?
刚刚来到这里,因为 Fatal 不调用 defer 导致资源(如数据库)没有被清理。我认为一般来说,应该避免使用 Fatal 而使用 Panic。仅当您确定代码中没有 defer(包括依赖项)时才使用 Fatal
m
mroman

panic 常用于小程序中,当出现您不知道如何处理或不想处理的错误时终止程序。 panic 的缺点正是:它将终止程序(大多数情况下,除非您使用 recover)。使用 panic 通常不好,除非您打算从中恢复,或者除非发生了某些事情,您真的无法恢复,或者您可以正常终止程序。例如,考虑一个为您提供功能的 API,但该 API 在某处秘密地有一个 panic,您注意到您的程序因此而在生产中终止。因此,您编写的任何代码的“外部 API”都应该从恐慌中恢复并返回错误。同样的事情也适用于终止程序的任何事情。

但是, os.Exit() 无法恢复,也无法执行延迟。