DEV Community

syossan27
syossan27

Posted on

How to implement a signal handler in Go

#go

This article explain "How to implement a signal handler in Go".

Also, I introduce a small library I made.

Introduction

This implement is assumed as follows.

  • Subscriber in PubSub
  • Show shutdown message
  • etc...

If knowing how to implement signal handlers, you can create programs with diversity in Go.

How to implement

The main points are as follows for implement.

  • Catch signal
  • Wait for caught signal

Catch signal

First, let's write program for catch signal.

Use "chan" for catch signal.

package main

import (
    "os"
    "os/signal"
)

func main() {
    signalCh := make(chan os.Signal, 1)
    signal.Notify(signalCh, os.Interrupt)
    <-signalCh
}
Enter fullscreen mode Exit fullscreen mode

This program is so simple.

Create os.Signal channel, and Receive os.Interrupt(= syscall.SIGINT) notify used signalCh.
As a side note, <-signalCh is wait for signalCh receive interrupt signal.

Wait for caught signal in goroutine

Since you can not do anything until you receive a signal, improve this program so that you can receive a signal with goroutine.

package main

import (
    "os"
    "os/signal"
)

func main() {
    doneCh := make(chan struct{})

    signalCh := make(chan os.Signal, 1)
    signal.Notify(signalCh, os.Interrupt)

    go receive(signalCh, doneCh)

    <-doneCh
}

func receive(signalCh chan os.Signal, doneCh chan struct{}) {
    for {
        select {
        // Example. Process to receive a message
        // case msg := <-receiveMessage():
        case <-signalCh:
            doneCh <- struct{}{}
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Execute the receive function using goroutine.

The receive function uses for and select and continues to move until you catch the signal.

When catching a signal, it sends an empty structure to doneCh and tells you that you caught the signal.

As an example, in the case of PubSub, we write a process to catch the message with the receive function.

Investigation

I investigated whether there is a library that can easily implement signal processing.

I found this library.

https://github.com/vrecan/death

However, in this library, it was troublesome to generate structure objects and create fixed structure methods.

Create

Therefore, I made a library called Tebata(手旗).

https://github.com/syossan27/tebata

Tebata can easily and flexibly create signal handler.

func main() {
    doneCh := make(chan struct{})

    t := tebata.New(os.Interrupt)
    t.Receive(func(ch chan struct{}){
        fmt.Println("Catch signal!")
        ch <- struct{}{}
    }, doneCh)

    <-doneCh
}
Enter fullscreen mode Exit fullscreen mode

Specify the signal you want to catch in the argument of New function.

Then, specify the function and argument you want to execute as the argument of the Receive function.

Only this.

If you want to implement a signal handler please try this library.

Top comments (0)