我知道你可以定义init
在任何包中调用的函数,这些函数将在main
. 我用它来打开我的日志文件和我的数据库连接。
有没有办法定义程序结束时将执行的代码,无论是因为它到达main
函数的末尾还是因为它被中断?我能想到的唯一方法是在 main 使用的每个包上手动调用延迟terminate
函数,但这非常冗长且容易出错。
我知道你可以定义init
在任何包中调用的函数,这些函数将在main
. 我用它来打开我的日志文件和我的数据库连接。
有没有办法定义程序结束时将执行的代码,无论是因为它到达main
函数的末尾还是因为它被中断?我能想到的唯一方法是在 main 使用的每个包上手动调用延迟terminate
函数,但这非常冗长且容易出错。
Go 开发人员考虑了Catexit
功能,并拒绝了采用它的想法。
来自golang-nuts的相关线程之一:
Atexit 在单线程、短命的程序中可能有意义,但我怀疑它是否在长时间运行的多线程服务器中占有一席之地。我见过许多 C++ 程序在退出时挂起,因为它们正在运行并不真正需要运行的全局析构函数,并且这些析构函数正在清理和释放无论如何都会被操作系统回收的内存,只要程序可以到达退出系统调用。与所有这些痛苦相比,当您使用缓冲区时需要调用 Flush 似乎是完全合理的,并且无论如何对于正确执行长时间运行的程序都是必要的。
即使忽略这个问题,atexit 引入了更多的控制线程,并且您必须回答诸如所有其他 goroutine 在 atexit 处理程序运行之前停止的问题吗?如果没有,他们如何避免干扰?如果是这样,如果一个人持有处理程序需要的锁怎么办?不断地。
我根本不倾向于添加 Atexit。
唯一完全可靠的机制是包装程序,它调用真实程序并在真实程序完成时进行清理。在任何语言中都是如此,而不仅仅是 Go。
在我有点不成熟的意见中, os.AtExit 不是一个好主意。它是一种非结构化工具,会导致程序退出时以不可预测的顺序发生某些事情。它会导致奇怪的场景,例如程序需要很长时间才能退出,而这个操作应该非常快。它还会导致奇怪的函数,如 C 函数 _exit,或多或少意味着退出但不运行 atexit 函数。
也就是说,我认为与 init 函数对应的特殊退出函数是一个有趣的想法。它将具有 os.AtExit 缺少的结构(即,退出函数的运行顺序与运行 init 函数时的顺序相反)。
但是,如果您的程序被内核杀死,或者因为您调用了一些违反分段的 C 代码而崩溃,退出函数将无济于事。
如果在阅读完所有这些(并且可能看过这个)之后,您仍然想要 atexit - 看看https://github.com/tebeka/atexit :)
总的来说,我同意 jnml 的回答。如果您仍然想这样做,您可以在函数中使用defer ,如下所示: http ://play.golang.org/p/aUdFXHtFOM 。main()