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

2

34

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.

Malinda answered 22/3, 2013 at 9:27 Comment(2)
If after reading all of this (and maybe watched this), you still want atexit - have a look at github.com/tebeka/atexit :)Pycno
Is this related question useful ? That's how I execute actions on end of execution.Fukien
M
41

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.

Malraux answered 22/3, 2013 at 9:36 Comment(0)
J
-1

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.

Jonahjonas answered 22/3, 2013 at 9:59 Comment(6)
Deferring functions from main only works when the program terminates by finishing main, not if it exits via os.Exit, in contrast to the original atexit which also works when calling exit.Stellular
Nor does it work when the program terminates with an unrecovered panic.Brayton
@Brayton You could, however, recover in the deferred function, so that's no real argument against defer in main.Leid
@nemo: Translating my comment to pseudo-code: if panic and not recover then not defer;.Brayton
It still won't get called if os.Exit is used.Hyperacidity
@Brayton it does call defer on panic play.golang.org/p/bxfsjsekTalBrentonbrentt

© 2022 - 2024 — McMap. All rights reserved.