2013-03-22 3 views
19

Я знаю, что вы можете определить функции под названием init в любом пакете, и эти функции будут выполнены до main. Я использую это, чтобы открыть мой файл журнала и мое соединение с БД.В go, есть ли способ выполнить код при завершении программы?

Есть ли способ определить код, который будет выполняться, когда программа закончится, либо потому, что она достигает конца функции main, либо потому, что она была прервана? Единственный способ, о котором я могу думать, - это вручную называть дефисную функцию terminate для каждого пакета, используемого основным, но это довольно многословно и подвержено ошибкам.

+1

ли [это связано вопрос] (http://stackoverflow.com/questions/8403862/do-actions-on-end-of-execution) полезно? Вот как я выполняю действия в конце выполнения. –

ответ

27

Функциональность C atexit была рассмотрена разработчиками Go, и идея ее принятия была отвергнута.

От одного родственного thread на golang орехи:

Russ Cox:

Atexit может иметь смысл в однопоточных, недолговечны программы, но я сомневаюсь, что у него есть место в длинном многопоточном сервере . Я видел много программ на C++, которые зависают на выходе, потому что они запускают глобальные деструкторы, которые действительно не нуждаются в запуске , и эти деструкторы очищают и освобождают память, которая будет исправлена ​​операционной системой в любом случае , если только программа может получить доступ к системному вызову выхода. По сравнению со всей этой болью, когда нужно позвонить Flush, когда вы находитесь , один с буфером кажется вполне разумным и необходим в любом случае для правильного выполнения долгосрочных программ .

Даже игнорируя эту проблему, atexit вводит еще больше нитей управления, и вы должны ответить на такие вопросы, как делают все другие goroutines остановки до atexit обработчиков перспективе? Если нет, то как им избежать вмешательства? Если да, то что, если содержит блокировку, которой нужен обработчик? И так далее.

Я совсем не склонен добавлять Atexit.

Ian Lance Taylor:

Единственные полностью надежный механизм является обертка программы, которая вызывает реальную программу и делает очистку, когда реальная программа завершается. То, что верно на любом языке, а не только на Go.

В моем несколько неоформленном мнении os.AtExit - отличная идея. Это неструктурированный объект, который заставляет вещи произойти при выходе программы время в непредсказуемом порядке. Это приводит к странным сценариям, например, программам, которые занимают много времени только для выхода, операция, которая должна быть очень быстро. Это также приводит к странным функциям, таким как функция C _exit, , которая в большей или меньшей степени означает функции exit-but-don't-run-atexit.

Это, я думаю, специальная функция выхода, соответствующая функции init , является интересной идеей. Он имел бы структуру, которая os.Недостатки AtExit (а именно, функции выхода выполняются в обратном порядке, когда запускаются функции init).

Но функции выхода не помогут вам, если ваша программа будет убита ядром , или выйдет из строя, потому что вы вызываете код C, который получает нарушение сегментации .

+2

Спасибо, это очень интересная тема. – Fabien

0

В целом, я согласен с ответом jnml. Если вы все еще хотите это сделать, вы можете использовать defer в функции main(), например: http://play.golang.org/p/aUdFXHtFOM.

+9

Функции отсрочки от 'main' работают только тогда, когда программа заканчивается, заканчивая' main', а не если она выходит через 'os.Exit', в отличие от исходного' atexit', который также работает при вызове 'exit'. – guelfey

+3

И это не работает, когда программа завершается с невосстановленной «паникой». – peterSO

+4

@peterSO Вы могли бы, однако, восстановиться в отложенной функции, так что это не реальный аргумент против 'defer' в' main'. – nemo

2

Если после прочтения всего этого (и, возможно, смотрел this), вы все еще хотите atexit - посмотреть на https://github.com/tebeka/atexit :)

+0

Пожалуйста, обновите ссылку на GitHub – ilyaigpetrov

+0

Сделано, спасибо @ilyaigpetrov – lazy1

Смежные вопросы