在Go语言中,是否有一种方法可以在程序终止时执行代码?

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

In go, is there a way to execute code on termination of the program?

问题

我知道你可以在任何包中定义名为init的函数,这些函数将在main之前执行。我使用这个来打开我的日志文件和数据库连接。

有没有一种方法可以定义在程序结束时执行的代码,无论是因为达到main函数的末尾还是因为被中断?我唯一能想到的方法是在main使用的每个包上手动调用一个延迟的terminate函数,但这样做非常冗长且容易出错。

英文:

I know you can define functions called init in any package, and these function will be executed before main. I use this to open my log file and my DB connection.

Is there a way to define code that will be executed when the program ends, either because it reaches the end of the main function or because it was interrupted ? The only way I can think of is by manually calling a deffered terminate function on each package used by main, but that's quite verbose and error prone.

答案1

得分: 40

C atexit功能被Go开发人员考虑过,并且拒绝了采用它的想法。

来自golang-nuts的相关讨论中的一条线索:

Russ Cox

> 在单线程、短生命周期的程序中,atexit可能是有意义的,但我对它在长时间运行的多线程服务器中是否有用持怀疑态度。
我见过很多C++程序在退出时挂起,因为它们运行了不需要运行的全局析构函数,而这些析构函数正在清理和释放本来会被操作系统回收的内存,只要程序能够到达退出系统调用。
与所有这些痛苦相比,当你使用缓冲区时需要调用Flush似乎是完全合理的,并且对于长时间运行的程序的正确执行来说是必要的。

> 即使忽略这个问题,atexit还引入了更多的控制线程,并且你必须回答诸如在atexit处理程序运行之前,所有其他goroutine是否停止的问题?如果不是,它们如何避免干扰?如果是,如果一个goroutine持有处理程序需要的锁会怎么样?等等。

> 我完全不想添加Atexit。

Ian Lance Taylor

> 唯一可靠的机制是一个包装程序,在真正的程序完成时调用它并进行清理。这在任何语言中都是正确的。

> 在我尚未形成的观点中,os.AtExit不是一个好主意。它是一个无结构的工具,导致在程序退出时以不可预测的顺序发生事情。它会导致奇怪的情况,比如需要很长时间才能退出的程序,这个操作应该非常快速。它还会导致奇怪的函数,比如C函数_exit,它或多或少意味着退出但不运行atexit函数。

> 话虽如此,我认为一个与init函数对应的特殊退出函数是一个有趣的想法。它将具有os.AtExit缺乏的结构(即,退出函数按照init函数运行的相反顺序运行)。

> 但是,如果你的程序被内核杀死,或者因为调用了一些C代码而导致段错误崩溃,退出函数是无法帮助你的。

英文:

The C atexit functionality was considered by the Go developers and the idea of adopting it was rejected.

From one of the related thread at golang-nuts:

Russ Cox:

> Atexit may make sense in single-threaded, short-lived
programs, but I am skeptical that it has a place in a
long-running multi-threaded server.
I've seen many C++ programs that hang on exit because
they're running global destructors that don't really need to
run, and those destructors are cleaning up and freeing
memory that would be reclaimed by the operating system
anyway, if only the program could get to the exit system call.
Compared to all that pain, needing to call Flush when you're
one with a buffer seems entirely reasonable and is
necessary anyway for correct execution of long-running
programs.

> Even ignoring that problem, atexit introduces even more
threads of control, and you have to answer questions like
do all the other goroutines stop before the atexit handlers
run? If not, how do they avoid interfering? If so, what if
one holds a lock that the handler needs? And on and on.

> I'm not at all inclined to add Atexit.

Ian Lance Taylor:

> The only fully reliable mechanism is a wrapper program that invokes the
real program and does the cleanup when the real program completes. That
is true in any language, not just Go.

> In my somewhat unformed opinion, os.AtExit is not a great idea. It is
an unstructured facility that causes stuff to happen at program exit
time in an unpredictable order. It leads to weird scenarios like
programs that take a long time just to exit, an operation that should be
very fast. It also leads to weird functions like the C function _exit,
which more or less means exit-but-don't-run-atexit-functions.

> That said, I think a special exit function corresponding to the init
function is an interesting idea. It would have the structure that
os.AtExit lacks (namely, exit functions are run in reverse order of when
init functions are run).

> But exit functions won't help you if your program gets killed by the
kernel, or crashes because you call some C code that gets a segmentation
violation.

答案2

得分: -2

总的来说,我同意jnml的答案。但是如果你仍然想要这样做,你可以在main()函数中使用defer,像这样:http://play.golang.org/p/aUdFXHtFOM。

英文:

In general, I agree with jnml's answer. Should you however still want to do it, you could use defer in the main() function, like this: http://play.golang.org/p/aUdFXHtFOM.

huangapple
  • 本文由 发表于 2013年3月22日 17:27:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/15566812.html
匿名

发表评论

匿名网友

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

确定