Control C Handling

There are a couple of options in the signal package for handling interrupts.

  • Have the signal written to a channel.
  • Have the signal cancel a context.

I’ve used the second method for handling control-c. The context returned is from context.WithCancel(..) which is a common (standard) way to notify child processing that it can stop. The context has a channel built in that is closed when the context is canceled. Anyone waiting on that channel will block until the channel is closed. The context can be read by multiple goroutines. You can also put the channel in a select{} clause for more flexibility.

    ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
    defer stop()

This context will then be used by the listener to close its connection

    go func() {
        <-ctx.Done()
        listener.Close()
    }()

And used by the web server to have it shutdown.

    go func() {
        <-ctx.Done()
        ...
        if err := srv.Shutdown(timeout); err != nil {...}
        ...
    }()