2013-03-22 27 views
19

Wiem, że można zdefiniować funkcje o nazwie init w dowolnym pakiecie, a ta funkcja zostanie wykonana przed main. Używam tego, aby otworzyć mój plik dziennika i moje połączenie DB.W go, czy istnieje sposób na wykonanie kodu po zakończeniu programu?

Czy istnieje sposób zdefiniowania kodu, który zostanie wykonany po zakończeniu programu, ponieważ dochodzi on do końca funkcji main lub został przerwany? Jedynym sposobem, jaki mogę wymyślić jest ręczne wywołanie funkcji deffered terminate na każdym pakiecie używanym przez main, ale jest to dość szczegółowe i podatne na błędy.

+1

Czy [to związane pytanie] (http://stackoverflow.com/questions/8403862/do-action-on-end-of-execution) przydatne? Tak wykonuję akcje po zakończeniu realizacji. –

Odpowiedz

27

Funkcjonalność C atexit została uznana przez twórców Go, a pomysł jej przyjęcia został odrzucony.

Z jednego powiązanego thread na golang orzechów:

Russ Cox:

atexit może mieć sens w jednowątkowy, krótkotrwały programy, ale jestem sceptyczny, że ma umieścić w długim, wielowątkowym serwerze . Widziałem wiele programów w języku C++, które zawieszają się przy wyjściu, ponieważ uruchamiają globalne destruktory, które naprawdę nie muszą działać, aby działały, a te destruktory czyszczą i zwalniają pamięć , która byłaby odzyskana przez system operacyjny . , gdyby tylko program mógł dostać się do wywołania systemowego wyjścia. W porównaniu do wszystkich tych bólów, które wymagają wywoływania Flush, gdy jesteś , jeden z buforem wydaje się być całkowicie uzasadniony i jest w każdym razie niezbędny do prawidłowej realizacji długotrwałych programów .

Nawet pomijając ten problem, atexit wprowadza jeszcze więcej tematów kontroli, i trzeba odpowiedzieć na pytania jak nie wszystkie inne goroutines powstrzymać przed Ładowarki atexit metę? Jeśli nie, w jaki sposób unikają ingerencji? Jeśli tak, co jeśli ma blokadę, której potrzebuje handler? I tak dalej.

Nie jestem wcale skłonny do dodania Atexit.

Ian Lance Taylor:

Jedynym całkowicie niezawodny mechanizm to program wrapper, który wywołuje prawdziwy program i robi porządki po zakończeniu rzeczywistego programu. To jest prawdziwe w każdym języku, a nie tylko Go.

W mojej nieco niesprecyzowanej opinii os.AtExit nie jest świetnym pomysłem. Jest to niestrukturalny obiekt, który powoduje, że rzeczy mogą się zdarzyć przy wyjściu z programu w nieprzewidywalnej kolejności. Prowadzi to do dziwnych scenariuszy, takich jak , które kończą się bardzo długo, co powinno być bardzo szybkie. Prowadzi to również do dziwnych funkcji, takich jak funkcja C _exit, , która w mniejszym lub większym stopniu oznacza funkcje wyjścia, ale nie działają.

To powiedziawszy, myślę, że specjalna funkcja wyjścia odpowiadająca funkcji init jest interesującym pomysłem. Miałaby strukturę, która jest os.AtExit nie ma (mianowicie, funkcje wyjścia są uruchamiane w odwrotnej kolejności, kiedy uruchamiane są funkcje inicjujące ).

Ale funkcje wyjścia nie pomogą, jeśli twój program zostanie zabity przez jądro , lub ulegnie awarii, ponieważ wywołujesz kod C, który dostaje naruszenie segmentacji .

+2

Dziękuję, to bardzo interesujący wątek. – Fabien

0

Ogólnie zgadzam się z odpowiedzią jnml. Jeśli jednak nadal chcesz to zrobić, możesz użyć funkcji defer w funkcji main(), na przykład: http://play.golang.org/p/aUdFXHtFOM.

+9

Funkcje odraczające z 'głównego' działają tylko wtedy, gdy program kończy się kończąc' main', a nie jeśli kończy się przez 'os.Exit', w przeciwieństwie do oryginalnego' atexit', który działa również podczas wywoływania 'exit'. – guelfey

+3

Nie działa również, gdy program kończy się nieodwracalnym 'paniką'. – peterSO

+4

@peterSO Można jednak odzyskać w funkcji odroczonej, więc nie ma prawdziwego argumentu przeciwko 'odraczaniu' w' main'. – nemo