`os.Exit()`和`panic()`分别在什么情况下使用?

huangapple go评论81阅读模式
英文:

When to use os.Exit() and panic()?

问题

os.Exit()panic()是Go语言中的两个不同的函数,它们在使用上有一些关键的区别。

os.Exit()函数用于立即终止程序的执行,并返回一个指定的退出状态码。它会终止当前的goroutine以及整个程序的执行,并且不会执行任何defer语句。通常情况下,os.Exit()函数用于表示程序遇到了无法恢复的错误或者需要立即停止执行的情况。

panic()函数用于引发一个运行时错误,并导致程序进入恐慌状态。当panic()函数被调用时,当前的函数调用会立即停止执行,并开始执行调用栈中的defer语句。如果没有被捕获的恐慌,程序会终止并打印出恐慌信息,包括调用栈的跟踪信息。通常情况下,panic()函数用于表示程序遇到了无法处理的错误或者不可恢复的状态。

在实践中,os.Exit()通常用于在程序的主函数中,当遇到严重错误时立即终止程序的执行。而panic()函数通常用于在函数内部遇到无法处理的错误或者异常情况时,将程序置于恐慌状态并进行相应的处理。

需要注意的是,os.Exit()函数会立即终止程序的执行,而panic()函数会触发恐慌状态并执行相应的恢复操作。因此,在使用这两个函数时需要根据具体的需求和场景进行选择。

英文:

Could someone explain the key differences between os.Exit() and panic() and how they are used in practice in Go?

答案1

得分: 127

首先,每当你有一个关于“在实践中如何使用”的问题时,一个好的起点是搜索 Go 源代码(或者任何足够大的 Go 代码库),以及包文档来获取答案。

现在,os.Exitpanic 是非常不同的。panic 在程序或其部分达到无法恢复的状态时使用。

当调用 panic 时,包括隐式地为运行时错误(如索引超出切片界限或类型断言失败)调用时,它会立即停止当前函数的执行,并开始解开 goroutine 的堆栈,同时运行任何延迟函数。如果该解开达到了 goroutine 堆栈的顶部,程序将终止。

os.Exit 用于立即中止程序,没有恢复的可能性,也没有运行延迟清理语句的机会,并返回一个错误代码(其他程序可以用来报告发生了什么)。这在测试中很有用,当你已经知道在这个测试失败后,其他测试也会失败,所以你可以立即退出。这也可以在程序完成了所有需要做的事情后使用,现在只需要退出,例如在打印帮助信息后。

大多数情况下,你不会使用 panic(应该返回一个 error),而且在测试中和快速程序终止的一些情况下,你几乎不需要使用 os.Exit

英文:

First of all, whenever you have a "how it is used in practice" question, a good way to start is to search the Go source code (or any big enough Go code base, really), and the package docs for answers.

Now, os.Exit and panic are quite different. panic is used when the program, or its part, has reached an unrecoverable state.

>When panic is called, including implicitly for run-time errors such as indexing a slice out of bounds or failing a type assertion, it immediately stops execution of the current function and begins unwinding the stack of the goroutine, running any deferred functions along the way. If that unwinding reaches the top of the goroutine's stack, the program dies.

os.Exit is used when you need to abort the program immediately, with no possibility of recovery or running a deferred clean-up statement, and also return an error code (that other programs can use to report what happened). This is useful in tests, when you already know that after this one test fails, the other will fail as well, so you might as well just exit now. This can also be used when your program has done everything it needed to do, and now just needs to exit, i.e. after printing a help message.

Most of the time you won't use panic (you should return an error instead), and you almost never need os.Exit outside of some cases in tests and for quick program termination.

答案2

得分: 112

首先,os.Exit() 可以用于正常退出程序而不报错,而 panic 则不行,这是一个关键的区别。另一个区别是,可以通过使用 recover 来捕获和忽略或记录某个地方的 panic。

但是,如果我们谈论的是错误的退出代码,比如说:

如果出现了严重错误,可能是程序员在发布之前应该捕获的错误,那么使用 panic。这就是为什么它会打印出堆栈信息。

如果你想要:

  1. 控制程序的退出代码以供脚本使用。

  2. 在预期的错误(例如用户输入错误)发生时有一个有序的退出。

那么可以使用 os.Exit(errorCode) 或类似的方法。

所以基本上,panic 是为了你自己,错误的退出代码是为了你的用户。

英文:

First of all, os.Exit() can be used to exit the program normally without an error, and panic not, so that's one key distinction. Another is that panic somewhere can be caught and ignored or logged using recover.

But if we're talking about an erroneous exit code, let's say:

Use panic when something goes horribly wrong, probably a programmer error that should have been caught before going to production. This is why it prints the stack.

Use os.Exit(errorCode) or something like that if you want to:

  1. control the exit code of the program for scripting purposes.

  2. want an orderly exit on an error that is expected (e.g user input error).

So basically panic is for you, a bad exit code is for your user.

答案3

得分: 17

关键区别如下:

  1. os.Exit 跳过了延迟执行的函数。
  2. 使用 os.Exit 可以指定退出码。
  3. panic 是终止的,而 os.Exit 不是。(似乎其他答案没有提到这一点。)

如果你需要执行延迟函数,只能使用 panic。(另一方面,如果你想跳过延迟函数的执行,使用 os.Exit。)

如果一个非空函数满足以下条件:

  1. 函数包含许多分支。
  2. 所有分支都以 returnpanic 结束。

那么你不能用 os.Exit 替换 panic,否则编译器会拒绝编译程序,提示“函数末尾缺少返回语句”。(在这方面,Go 非常愚蠢,即使 log.Panic 也不能终止函数。)

在其他情况下:

  1. 当发生真正奇怪的事情时,例如编程逻辑错误,使用 panic
  2. 当你想要立即退出,并指定退出码时,使用 os.Exit
英文:

The key differences are:

  1. os.Exit skips the execution of deferred function.
  2. With os.Exit, you can specify the exit code.
  3. panic is terminating while os.Exit is not. (Seems other answers do not mention this.)

If you need to execute the deferred function, you have no choice but panic. (On the other hand, if you want to skip execution of deferred function, use os.Exit.)

If a non-void function is defined in such a way:

  1. the function contains a lot of branches
  2. all branches are terminated with return or panic

Then you cannot replace panic with os.Exit otherwise the compiler will refuse to compile the program, saying "missing return at end of function". (Go is very dumb here, even log.Panic does not terminate a function.)

Under other conditions:

  1. Use panic when something really wired happens, e.g. programming logic error.
  2. Use os.Exit when you want an immediate exit, with specified exit code.

huangapple
  • 本文由 发表于 2015年2月12日 16:45:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/28472922.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定