package service import ( "context" "errors" "fmt" "log" "net/http" "sync" "time" ) // HTTPServer 封装HTTP服务器功能 type HTTPServer struct { server *http.Server wg sync.WaitGroup } // NewServer 创建一个新的HTTP服务器实例 func NewServer(addr string, handler http.Handler) *HTTPServer { return &HTTPServer{ server: &http.Server{ Addr: addr, Handler: handler, }, } } // Start 启动HTTP服务器(在协程中),支持context func (s *HTTPServer) Start(ctx context.Context) error { log.Printf("HTTP服务器正在启动,监听地址: %s", s.server.Addr) // 监听context取消信号 shutdownChan := make(chan struct{}) go func() { <-ctx.Done() log.Println("接收到context取消信号,开始关闭服务器...") close(shutdownChan) }() s.wg.Add(1) go func() { defer s.wg.Done() if err := s.server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { log.Printf("服务器启动失败: %v", err) return } }() // 给服务器一点启动时间 time.Sleep(100 * time.Millisecond) // 等待服务器启动完成或context取消 select { case <-shutdownChan: // 如果context在启动过程中被取消,立即关闭服务器 if err := s.Stop(); err != nil { log.Printf("启动过程中关闭服务器失败: %v", err) } return ctx.Err() default: log.Println("HTTP服务器启动成功") return nil } } // Stop 优雅关闭HTTP服务器 func (s *HTTPServer) Stop() error { log.Println("正在关闭HTTP服务器...") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := s.server.Shutdown(ctx); err != nil { return fmt.Errorf("服务器关闭失败: %v", err) } // 等待服务器协程结束 s.wg.Wait() log.Println("HTTP服务器已成功关闭") return nil } // StartWithContext 可选:提供一个更简洁的启动方法(如果你需要) func (s *HTTPServer) StartWithContext(ctx context.Context) <-chan error { errChan := make(chan error, 1) go func() { errChan <- s.Start(ctx) close(errChan) }() return errChan }