When using http.ListenAndServe()
in Go, this results in a blocking situation where the application, apparently, can only be stopped by killing it. This seems to skip processing my defer
statements. Please see the code below. When I kill the application the db is not closed. How can I make sure my defer
statement will be run?
func main() {
db := NewDB(DBFILENAME)
defer db.Close()
http.HandleFunc("/", handler)
http.ListenAndServe(":80", nil)
}
defer
statements get executed only when the function enclosing them returns. Your main function is not returning when you kill it. So you need to use signals and channels.
This is a good link explaining the same https://www.socketloop.com/tutorials/golang-intercept-ctrl-c-interrupt-or-kill-signal-and-determine-the-signal-type .
I faced the same problem with my last project. I implemented a similar solution in my project wshare .
In your case, you can try something like
ch := make(chan os.Signal, 3)
signal.Notify(ch, os.Interrupt,syscall.SIGTERM,syscall.SIGINT)
go func() {
signalType := <-ch
signal.Stop(ch)
log.Println("Exit command received. Exiting...")
// this is a good place to flush everything to disk
// before terminating.
db.Close()
log.Println("Signal type : ", signalType)
os.Exit(0)
}()
The HTTP package in the next go release 1.8 will have a new Shutdown function that gracefully shuts down the server . https://beta.golang.org/pkg/net/http/#Server.Shutdown I suppose that defer will work then.