Signals

Сигнали|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