33

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.

Fabien
  • 12,486
  • 9
  • 44
  • 62
  • 1
    Is [this related question](http://stackoverflow.com/questions/8403862/do-actions-on-end-of-execution) useful ? That's how I execute actions on end of execution. – Denys Séguret Mar 23 '13 at 13:41
  • If after reading all of this (and maybe watched [this](http://pyvideo.org/video/647/make-sure-your-programs-crash)), you still want atexit - have a look at https://github.com/tebeka/atexit :) – Miki Tebeka Mar 22 '13 at 20:40

2 Answers2

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.

zzzz
  • 87,403
  • 16
  • 175
  • 139
-2

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.

Thomas Kappler
  • 3,795
  • 1
  • 22
  • 21
  • 17
    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`. – guelfey Mar 22 '13 at 12:47
  • 4
    Nor does it work when the program terminates with an unrecovered `panic`. – peterSO Mar 22 '13 at 13:04
  • 4
    @peterSO You could, however, recover in the deferred function, so that's no real argument against `defer` in `main`. – nemo Mar 22 '13 at 18:42
  • 1
    @nemo: Translating my comment to pseudo-code: `if panic and not recover then not defer;`. – peterSO Mar 22 '13 at 20:36
  • 1
    It still won't get called if os.Exit is used. – 0xcaff Apr 30 '14 at 16:58
  • 1
    @peterSO it does call defer on panic https://play.golang.org/p/bxfsjsekTal – Noobie May 11 '21 at 15:51