originally posted to blob.web-apps.tech
Using github.com/nasa9084/syg
, you can map signal to callback function easily.(c.f. syg: simply signal to callback mapping in Go)
Now, let's implement a HTTP server which shuts down gracefully when catch SIGINT.
package app
import (
"context"
"net/http"
"os"
"time"
"github.com/nasa9084/syg"
)
type Server struct {
server *http.Server
closed chan struct{}
}
func NewServer() *Server {
http.HandleFunc("/", longlongHandler)
return &Server{
server: &http.Server{
Addr: ":8080",
},
closed: make(chan struct{}),
}
}
func (s *Server) Run() error {
// os.Interrupt = syscall.SIGINT
cancel := syg.Listen(s.shutdown, os.Interrupt)
defer cancel()
err := s.server.ListenAndServe()
<-s.closed
return err
}
func (s *Server) shutdown(os.Signal) {
s.Shutdown(context.Background())
close(s.closed)
}
func longlongHandler(w http.ResponseWriter, r *http.Request) {
// a very long process!
time.Sleep(10 * time.Second)
w.Write([]byte("hello"))
}
call from main:
package main
import (
"log"
"foo/bar/app" // assume the app package above is in $GOPATH/foo/bar/app
)
func main() {
s := app.NewServer()
if err := s.Run(); err != http.ErrServerClosed {
log.Print(err)
}
}
In main, you don't need to think goroutine, graceful shutdown, or signal listening.
Check the server is running well.
At first, build and run the server:
$ go build main.go
$ ./main
Then launch one more Terminal, and send a request:
$ curl localhost:8080
hello
after 10 seconds, message "hello" is returned.
Now, send request once again, type Ctrl-C
(this means SIGINT) in the first terminal before returned the response.
The server will shut down after return the response, not suddenly.
We did it!
Top comments (0)