When you want to catch system signals in Go, you can use os
package, os/signal
package, and syscall
package.
Here's an example of catching a system signal then shutdown the HTTP server gracefully:
func main() {
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT)
s := &http.Server{
// configure server properties
}
go func() {
<-sigCh
s.Shutdown(context.Background())
}()
if err := s.ListenAndServe(); err != http.ErrServerClosed {
// error handling
}
}
Yes, this is a very simple pattern.
If server downed with some error before signal is sent, the goroutine which listening the signal will leak.
So, we use context
and for-select loop.
func main() {
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT)
s := &http.Server{
// configure server properties
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
for {
select {
case <-sigCh:
s.Shutdown(context.Background())
case <-ctx.Done():
return
}
}
}()
if err := s.ListenAndServe(); err != http.ErrServerClosed {
// error handling
}
}
Hmmm.... This is also a very simple pattern, there's no error handling code, no server configure, or no flag parsing.
However, the code is so complex. I cannot remember this signal catch idiom.
So I created github.com/nasa9084/syg
package for listen signals and call a callback function.
github.com/nasa9084/syg
Rethink the example code.
I rewrite the example code with syg
package:
func main() {
s := &http.Server{
// configure server properties
}
cancel := syg.Listen(func(os.Signal) {
s.Shutdown(context.Background())
}, syscall.SIGINT)
defer cancel()
if err := s.ListenAndServe(); err != http.ErrServerClosed {
// error handling
}
}
Wow, very shortened.
The syg
package has only two function, Listen()
and ListenContext()
.
As you thought, these are essentially same function.
ListenContext()
takes context.Context
, but Listen()
is not.
Listen()
calls context.Background()
inside the function, and calls ListenContext()
with that context.
These functions calls signal.Notify()
and generates goroutine which waits the signal, and returns the cancel function.
syg
package is very small package, but it is very useful.
Please use this package and make issues or PR if you find problems or enhancements!
Top comments (0)