Go в примерах: Сигналы (Signals)

Иногда вам понадобится чтобы ваша Go программа умела обрабатывать Сигналы (UNIX). Например, вы возможно захотите сервер с поддержкой обработки соединений (graceful) в момент когда программа получает сигнал на завершение (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, мы посылаем SIGINT. При его обработке программа выведет interrupt и завершится.

$ go run signals.go
awaiting signal
^C
interrupt
exiting

Следующий пример: Выход (Exit).