#best-practice #development #golang #pattern

If you have long-running processes in Go, you often need a way to properly shutdown the application. The common way to do this is to perform some action when the user presses CTRL+C on their keyboard.

In Linux/Unix, doing a CTRL+C sends a signal SIGINT (the interrupt signal) to the process. How do we catch this in a Go application and do something with it?

Go defines the signal.Notify method which can be used for this.

This is the example taken from the Go docs which shows how to use this:

 1package main
 2
 3import (
 4    "fmt"
 5    "os"
 6    "os/signal"
 7)
 8
 9func main() {
10
11    // Set up channel on which to send signal notifications.
12    // We must use a buffered channel or risk missing the signal
13    // if we're not ready to receive when the signal is sent.
14    c := make(chan os.Signal, 1)
15    signal.Notify(c, os.Interrupt)
16
17    // Block until a signal is received.
18    s := <-c
19
20    // The signal is received, you can now do the cleanup
21    fmt.Println("Got signal:", s)
22
23}

In most programs like these, you will start the main part of the app in a goroutine (otherwise, they will block the handling of CTRL+C).

For example, it might be that you run an infinite loop:

 1package main
 2
 3import (
 4    "fmt"
 5    "os"
 6    "os/signal"
 7    "time"
 8)
 9
10func main() {
11
12    // Run the main part of the app in a goroutine
13    go func() {
14        for {
15            fmt.Println("Doing something")
16            time.Sleep(2 * time.Second)
17        }
18    }()
19
20    // Set up channel on which to send signal notifications.
21    // We must use a buffered channel or risk missing the signal
22    // if we're not ready to receive when the signal is sent.
23    c := make(chan os.Signal, 1)
24    signal.Notify(c, os.Interrupt)
25
26    // Block until a signal is received.
27    s := <-c
28
29    // The signal is received, you can now do the cleanup
30    fmt.Println("Got signal:", s)
31
32}

As you can see, once you understand the idea behind channels and goroutines, doing things like these is really simple.