从 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{})
看起来恐慌没有返回任何东西。
这是主要区别吗?否则,假设恐慌没有恢复,它们似乎在应用程序中执行相同的功能。
日志消息会发送到配置的日志输出,而 panic 只会写入 stderr。
恐慌将打印一个堆栈跟踪,这可能与错误根本无关。
当程序 panic 时会执行 defers,但调用 os.Exit 会立即退出,并且无法运行 deferred 函数。
通常,仅将 panic
用于编程错误,其中堆栈跟踪对于错误的上下文很重要。如果消息不是针对程序员的,那么您只是将消息隐藏在多余的数据中。
panic
常用于小程序中,当出现您不知道如何处理或不想处理的错误时终止程序。 panic
的缺点正是:它将终止程序(大多数情况下,除非您使用 recover
)。使用 panic
通常不好,除非您打算从中恢复,或者除非发生了某些事情,您真的无法恢复,或者您可以正常终止程序。例如,考虑一个为您提供功能的 API,但该 API 在某处秘密地有一个 panic
,您注意到您的程序因此而在生产中终止。因此,您编写的任何代码的“外部 API”都应该从恐慌中恢复并返回错误。同样的事情也适用于终止程序的任何事情。
但是, os.Exit() 无法恢复,也无法执行延迟。
t.Fatal
/t.Fatalf
vs log in 测试)Fatal
不执行延迟的事实是 IMO 的一个大问题,我看不出这如何使其成为可行的解决方案。例如,因为我的程序不会清理它的临时目录......log.Fatal
。也许?Fatal
不调用 defer 导致资源(如数据库)没有被清理。我认为一般来说,应该避免使用Fatal
而使用Panic
。仅当您确定代码中没有defer
(包括依赖项)时才使用Fatal
。