我需要使用defer
来释放使用C
库手动创建的分配,但我还需要在某个时候使用非0状态的os.Exit
。棘手的部分是os.Exit
跳过任何延迟指令:
package main
import "fmt"
import "os"
func main() {
// `defer`s will _not_ be run when using `os.Exit`, so
// this `fmt.Println` will never be called.
defer fmt.Println("!")
// sometimes ones might use defer to do critical operations
// like close a database, remove a lock or free memory
// Exit with status code.
os.Exit(3)
}
Playground:http://play.golang.org/p/CDiAh9SXRM从https://gobyexample.com/exit被盗
那么如何退出一个支持已声明的defer
调用的go程序呢?有没有os.Exit
的替代品?
4条答案
按热度按时间toe950271#
只需将程序向下移动一级并返回退出代码:
ovfsdjhp2#
runtime.Goexit()
是实现这一点的简单方法。Goexit终止调用它的goroutine。其他goroutine不受影响。**Goexit在终止goroutine之前运行所有的延迟调用。**因为Goexit不是panic,但是,这些延迟函数中的任何recover调用都将返回nil。
然而:
从主goroutine调用Goexit会终止该goroutine而不返回func main。由于func main没有返回,程序继续执行其他goroutine。如果所有其他goroutine退出,程序就会崩溃。
因此,如果你从主goroutine调用它,在
main
的顶部,你需要添加在下面,你可能想添加一些其他的
defer
语句,通知其他的goroutine停止并清理。62lalag43#
经过一些研究,参考这个this,我发现了一个替代方案:
我们可以利用
panic
和recover
。事实证明,panic
本质上会荣誉defer
调用,但也总是以非0
状态码退出并转储堆栈跟踪。诀窍是我们可以使用以下命令覆盖panic行为的最后一个方面:现在,要在任何时候退出程序并仍然保留任何声明的
defer
指令,我们只需要发出一个Exit
类型:除了在
func main
中插入一条线外,它不需要任何重构:这在较大的代码库中扩展得很好,所以我将它留给仔细检查。希望有帮助。
Playground:http://play.golang.org/p/4tyWwhcX0-
oiopk7p54#
对后代来说,对我来说,这是一个更优雅的解决方案: