Graceful Server—Wait and Shutdown
Explore how to keep your Go backend server running using channels and implement a graceful shutdown that handles OS signals like SIGTERM and SIGINT effectively. This lesson teaches you to manage server lifecycle events for robust and reliable backend services.
We'll cover the following...
Wait while listening
Our core problem so far is that our main thread is exiting, causing our server to die. To prevent that, we will use a channel. We will keep listening on it, therefore ensuring our main thread doesn’t quit.
package main
import (
"fmt"
"io"
"net"
"net/http"
)
var port = "8080"
type gracefulServer struct {
httpServer *http.Server
listener net.Listener
}
func (server *gracefulServer) start() error {
listener, err := net.Listen("tcp", server.httpServer.Addr)
if err != nil {
return err
}
server.listener = listener
go server.httpServer.Serve(server.listener)
fmt.Println("Server now listening on " + server.httpServer.Addr)
return nil
}
func handle(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello student!\n")
}
// Initialize a new server instance and return reference.
func newServer(port string) *gracefulServer {
mux := http.NewServeMux()
mux.HandleFunc("/", handle)
httpServer := &http.Server{Addr: ":" + port, Handler: mux}
return &gracefulServer{httpServer: httpServer}
}
func main() {
done := make(chan struct{})
server := newServer(port)
server.start()
<-done
}Take a look at lines 42 and 45 in the code above. We create a channel, and we wait on it. Therefore, we have created a never-ending wait for our goroutine to run peacefully. Let’s try it out.
Run the code. Wait for the message saying, “The server is listening.”
Launch a new terminal and run the
curl localhost:8080command.
Voilà! We have successfully managed to start the server! But what about shutting it down? Let’s add a server method for that as ...