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