Сигнали|Signals
#
// Інколи виникає необхідність реагувати на
// [Сигнали операційної системи (Unix)](https://uk.wikipedia.org/wiki/Сигнал_(операційні_системи))
// не так, як задумано. Це буває корисно наприклад у випадках, коли потрібно
// щоб сервер обережно завершив свою роботу по отриманні сигналу `SIGTERM`,
// або програма що працює з командним рядком зупинили обробку вводу - по отриманні`SIGINT`.
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
)
func main() {
// Нотифікації сигналів у Go працюють за допомогою передачі
// значення `os.Signal` через канал. Ми створимо канал для
// отримання таких повідомлень, ми також створимо ще один канал
// для повідомлення про завершення програми.
sigs := make(chan os.Signal, 1)
// `signal.Notify` реєструє зазначений канал для отримання
// повідомлень переданих сигналів. Як тільки таккий сигнал
// буде зареєстровано - він буде переданий в канал.
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
// Ми можемо отримувати від `sigs`, але давайте розглянемо
// як це можливо реалізувати в окремій горутині, для
// демонстрації більш реалістичного сценарію елегантного виходу.
done := make(chan bool, 1)
// Ця горутинка - виконає блокування поки не буде отримано
// сигнал з каналу. Як тільки такий сигнал буде їй передано -
// вона виведе повідомлення і повідомить програму, що їй пора
// завершуватись.
go func() {
sig := <-sigs
fmt.Println()
fmt.Println(sig)
done <- true
}()
// Програма чекатиме тут допоки вона не отримає очікуваний
// сигнал (як визначено горутинкою вище - що має надіслати в
// `done` значення), після чого вона завершить роботу.
fmt.Println("awaiting signal")
<-done
fmt.Println("exiting")
}
# Як тільки ми запустимо цю програму вона "заблокується"
# і буде очікувати сигнал. Натискаючи `ctrl-C`
# (який показано тут як `^C`) ми передамо сигнал `SIGINT`,
# що змусить програму надрукувати `interrupt` і завершити
# роботу.
$ go run signals.go
awaiting signal
^C
interrupt
exiting