Skip to content

Instantly share code, notes, and snippets.

@koron
Created October 5, 2017 15:47
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save koron/8ae9d2e27182f145466ce5794af7c01e to your computer and use it in GitHub Desktop.
Save koron/8ae9d2e27182f145466ce5794af7c01e to your computer and use it in GitHub Desktop.
Sample http.Server with Shutdown
package main
import (
"context"
"log"
"net/http"
"os"
"os/signal"
"time"
)
func serve() error {
// サーバーの準備
http.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
w.Write([]byte("Hello, example http server\n"))
})
s := http.Server{Addr: ":8080"}
// goroutine 間通信のためのチャンネルの作成とその後片付けを予約
sig := make(chan os.Signal, 1)
cherr := make(chan error, 1)
defer func() {
close(cherr)
close(sig)
}()
// シグナルモニタリングのループ
go func() {
for {
s := <-sig
if s == os.Interrupt {
break
}
}
signal.Stop(sig)
// シャットダウンを無限に待っても良いけど、
// 15秒でタイムアウトするようにした
ctx, _ := context.WithTimeout(context.Background(), 15*time.Second)
err := s.Shutdown(ctx)
if err == nil {
// 綺麗に終わったらログを出す
log.Printf("shutdown HTTP server gracefully")
}
cherr <- err
}()
// シグナルを受け付け始めてサーバーを起動
signal.Notify(sig, os.Interrupt)
err := s.ListenAndServe()
if err == http.ErrServerClosed {
// シャットダウンされた場合はその完了を待ち、そちらのエラーを返す
return <-cherr
}
// それ以外はサーバーが返したエラーをそのまま返す
return err
}
func main() {
err := serve()
if err != nil {
// サーバーがエラー返したらログに吐く
log.Print(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment