Много раз вы оказываетесь в ситуации, когда вам приходится ждать завершения долгой задачи, возможно, вывод практически не доступен, и в конечном итоге вы нажимаете Ctrl-C, вводя SIGINT в программное обеспечение CLI.

И это прекращается.

Не выводя все, что вам нужно, и даже не печатая небольшой прогресс. И это немного расстраивает, хотя, вероятно, он работает так, как ожидалось, принимая во внимание то, что делает SIGINT.

Итак, как нам представить классическое «вы действительно хотите выйти?» подтверждение в программном обеспечении Go CLI?

Код вышеприведенной программы можно увидеть здесь:

У нас есть структура Thing, которая наследует тип sync.Mutex, что позволяет ей иметь простой механизм блокировки/разблокировки. Метод DoTask просто блокирует структуру, устанавливает текущий индекс, некоторое время засыпает, эмулируя тяжелую работу, а затем разблокирует структуру. Ничего слишком сложного.

Перехват SIGINT в программе Go включает в себя создание (буферизованного) канала типа os.Signal, а затем использование signal.Notify(c chan<- os.Signal, sig …os.Signal) для ретрансляции указанных сигналов — в нашем случае os.Interrupt`— в канал, который мы создали ранее.

Так как же сделать его интерактивным? Как сказать нашему воркеру приостановить или прекратить работу над сигналом SIGINT? Ну, теперь это довольно просто, учитывая, что наша структура Thing уже имеет механизм блокировки и разблокировки.

Нам нужно только (ab) использовать мьютекс и блокировку при перехвате сигнала.

Что, если нам не нужно получать пользовательский ввод, а нужно только выйти (изящно)? Предположим, мы хотим изящно остановить работающий воркер по сигналу SIGINT, но горутина каким-то образом блокирует его, и сколько бы раз мы ни посылали сигнал SIGINT, он просто будет стоять и ничего не делать?

Мы могли бы посчитать полученные сигналы и форсировать не очень изящный выход.

Вот оно. Это всего лишь пример того, как можно поймать и использовать сигнал ОС. Красивая печать и очистка остаются упражнением для читателя.

Это ранее было опубликовано в моем блоге: https://www.vlads.me/2017/09/04/catch-multiple-sigints-in-go-confirm-if-you-really-want-to- выйти/