Tratando sinais com Go

Tratar sinais é uma boa prática. Dessa forma, você pode finalizar seu programa graciosamente, liberando recursos e fechando bancos de dados, em vez de simplesmente encerrar o programa. Tratar sinais do sistema operacional com Golang é simples, pois o sistema envia o sinal para um canal. Basta escutar esse canal.

Primeiro, criamos um canal:

sc := make(chan os.Signal, 1)

Em seguida, informamos o tipo de sinal que nos interessa. No caso, ^C, ou seja, SIGINT.

signal.Notify(sc, os.Interrupt)

Você pode informar mais de um sinal. Basta adicionar mais argumentos, por exemplo: signal.Notify(sc, os.Interrupt, syscall.SIGTERM).

Os sinais que considero mais interessantes de tratar são:

  • os.Interrupt: igual a syscall.SIGINT, representa o sinal ^C
  • syscall.SIGTERM: sinal de terminação, geralmente enviado pelo comando kill
  • syscall.SIGWINCH: sinal de redimensionamento de janela (quando o terminal é redimensionado)
  • syscall.SIGUSR1: sinal de usuário 1 (você pode criar seus próprios sinais)
  • syscall.SIGUSR2: sinal de usuário 2

Então, basta aguardar o canal receber um sinal.

<-sc

Você precisa tratar os sinais em uma goroutine.

Exemplo

go func() {
    sc := make(chan os.Signal, 1)
    signal.Notify(
        sc,
        os.Interrupt,
        syscall.SIGTERM,
        syscall.SIGWINCH,
        syscall.SIGUSR1,
        syscall.SIGUSR2)
    for {
        s := <-sc
        switch s {
        case os.Interrupt:
            fmt.Printf("\r\nVocê pressionou ^C\r\n")
            os.Exit(0)
        case syscall.SIGTERM:
            fmt.Printf("\r\nVocê enviou SIGTERM\r\n")
            os.Exit(0)
        case syscall.SIGUSR1:
            fmt.Printf("\r\nVocê enviou SIGUSR1\r\n")
        case syscall.SIGUSR2:
            fmt.Printf("\r\nVocê enviou SIGUSR2\r\n")
        case syscall.SIGWINCH:
            fmt.Printf("\r\nA janela foi redimensionada\r\n")
        }
    }
}()

c := make(chan struct{})
<-c

código fonte completo

Os sinais SIGUSR1 e SIGUSR2 são sinais de usuário. Você pode criar seus próprios sinais para, por exemplo, solicitar informações ou alterar o comportamento do programa.

Para enviar sinais de usuário, use o comando kill com a opção -USR1 ou -USR2.

kill -USR1 <pid>

O sinal SIGWINCH é enviado quando a janela do terminal é redimensionada. Você pode usá-lo para capturar as novas dimensões e redimensionar a janela do seu programa.

Os sinais SIGTERM e SIGINT são sinais de terminação. O primeiro é enviado pelo comando kill, e o segundo é enviado quando o usuário pressiona ^C. Você pode usá-los para finalizar o programa graciosamente, fechando conexões e liberando recursos.

Vídeo com a explicação:

Cesar Gimenes

Última modificação