func main() {
    var wg sync.WaitGroup

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, Signal!\\n")
    })
    var srv = http.Server{
        Addr: "localhost:8080",
    }

    srv.RegisterOnShutdown(func() {
        fmt.Println("clean resources on shutdown...")
        time.Sleep(2 * time.Second)
        fmt.Println("clean resources ok")
        wg.Done()
    })

    wg.Add(2)
    go func() {
        quit := make(chan os.Signal, 1)
        signal.Notify(quit, syscall.SIGINT,
           syscall.SIGTERM,
           syscall.SIGQUIT,
           syscall.SIGHUP)

        <-quit

        timeoutCtx, cf := context.WithTimeout(context.Background(),
            time.Second*5)
        defer cf()
        var done = make(chan struct{}, 1)
        go func() {
            if err := srv.Shutdown(timeoutCtx); err != nil {
                fmt.Printf("web server shutdown error: %v", err)
            } else {
                fmt.Println("web server shutdown ok")
            }
            done <- struct{}{}
            wg.Done()
        }()

        select {
        case <-timeoutCtx.Done():
            fmt.Println("web server shutdown timeout")
        case <-done:
        }
    }()

    err := srv.ListenAndServe()
    if err != nil {
        if err != http.ErrServerClosed {
            fmt.Printf("web server start failed: %v\\n", err)
            return
        }
    }
    wg.Wait()
    fmt.Println("program exit ok")
}