...

/

Graceful Server—Wait and Shutdown

Graceful Server—Wait and Shutdown

Learn how to wait and listen after starting the server. Also, learn how to gracefully shut it down by listening to kill signals.

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
}
Using channels to wait

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:8080 command.

Voilà! We have ...