Go за Прикладом: Сигнали

Work in Progress / Сайт в процесі розробки

Інколи виникає необхідність нашим Go програмам розумно реагувати на Сигнали операційної системи (Unix). Наприклад, ми може захотіти щоб сервер обережно завершив роботу при отриманні сигналу SIGTERM, або програма що працює з командним рядком зупинили обробку вводу якщо вона отримає SIGINT. І ось як працвати з сигналами в Go’шних каналах.

package main
import "fmt"
import "os"
import "os/signal"
import "syscall"
func main() {

Нотифікації сигналів у Go працюють наступним чином - надсилається значення os.Signal через канал. Ми створемо канал для отримання таких нотифікацій (ми також створимо ще один канал для нотифікації завершення програми).

    sigs := make(chan os.Signal, 1)
    done := make(chan bool, 1)

signal.Notify реєструє зазначений канал для отримання нотифікацій зазначених сигналів.

    signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

Ця горутинка виконує блокуюче отримання для сигналів. Як тільки такий сигнал буде їй передано - вона надрукує нотифікацію і повідомить программу що їй пора завершуватись.

    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

Наступний приклад: Exit.