Last active
November 13, 2024 20:20
-
Star
(139)
You must be signed in to star a gist -
Fork
(35)
You must be signed in to fork a gist
-
-
Save peterhellberg/38117e546c217960747aacf689af3dc2 to your computer and use it in GitHub Desktop.
*http.Server in Go 1.8 supports graceful shutdown. This is a small example.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"log" | |
"net/http" | |
"os" | |
"os/signal" | |
"time" | |
) | |
type Server struct { | |
logger *log.Logger | |
mux *http.ServeMux | |
} | |
func NewServer(options ...func(*Server)) *Server { | |
s := &Server{ | |
logger: log.New(os.Stdout, "", 0), | |
mux: http.NewServeMux(), | |
} | |
for _, f := range options { | |
f(s) | |
} | |
s.mux.HandleFunc("/", s.index) | |
return s | |
} | |
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { | |
s.mux.ServeHTTP(w, r) | |
} | |
func (s *Server) index(w http.ResponseWriter, r *http.Request) { | |
s.logger.Println("GET /") | |
w.Write([]byte("Hello, World!")) | |
} | |
func main() { | |
stop := make(chan os.Signal, 1) | |
signal.Notify(stop, os.Interrupt) | |
logger := log.New(os.Stdout, "", 0) | |
addr := ":" + os.Getenv("PORT") | |
if addr == ":" { | |
addr = ":2017" | |
} | |
s := NewServer(func(s *Server) { s.logger = logger }) | |
h := &http.Server{Addr: addr, Handler: s} | |
go func() { | |
logger.Printf("Listening on http://0.0.0.0%s\n", addr) | |
if err := h.ListenAndServe(); err != nil { | |
logger.Fatal(err) | |
} | |
}() | |
<-stop | |
logger.Println("\nShutting down the server...") | |
ctx, _ := context.WithTimeout(context.Background(), 5*time.Second) | |
h.Shutdown(ctx) | |
logger.Println("Server gracefully stopped") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, great contribution.
There is one thing that could make it more complete in my opinion.
Everywhere this code is, it will always print "Listening on http://...." in the console, even if
ListenAndServe()
was unable to start actually listening.If you start 1 server, you'll see this in the console:
If you start a 2nd server without shutting down the 1st one, you will see this in the console:
Listening on http://0.0.0.0:2017 panic... listen tcp :2017: bind: address already in use
So it first shows "Listening on http://..." however this never actually happened.
I'm not a go expert, is there a way to implement this?
-- UPDATE
Apparently using
http.Listen
andhttp.Serve
individually, it is possible to catch a port in use error (or any other error while trying to listen to a tcp network) before assuming the server is listening.Source: https://stackoverflow.com/a/48250354/194630