// Package server 提供 HTTP 服务与优雅启停。 package server import ( "context" "errors" "log/slog" "net/http" "os/signal" "syscall" "time" ) // Server 封装 http.Server 与优雅关闭。 type Server struct { http *http.Server log *slog.Logger } // New 创建 Server。 func New(addr string, handler http.Handler, log *slog.Logger) *Server { return &Server{ http: &http.Server{ Addr: addr, Handler: handler, ReadHeaderTimeout: 10 * time.Second, ReadTimeout: 30 * time.Second, WriteTimeout: 30 * time.Second, IdleTimeout: 60 * time.Second, }, log: log, } } // Run 启动并阻塞,直到收到 SIGINT/SIGTERM 完成优雅关闭。 func (s *Server) Run() error { ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() errCh := make(chan error, 1) go func() { s.log.Info("server: listening", "addr", s.http.Addr) errCh <- s.http.ListenAndServe() }() select { case err := <-errCh: if errors.Is(err, http.ErrServerClosed) { return nil } return err case <-ctx.Done(): s.log.Info("server: shutting down") shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() return s.http.Shutdown(shutdownCtx) } }