package tcp import ( "context" "net" "os" "os/signal" "sync" "syscall" "github.com/runningwater/go-redis/interface/tcp" "github.com/runningwater/go-redis/lib/logger" ) type Config struct { Address string } func ListenAndServeWithSignal(cfg *Config, handler tcp.Handler) error { closeChan := make(chan struct{}) sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT) //nolint:govt go func() { sig := <-sigChan switch sig { case syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT: closeChan <- struct{}{} } }() listener, err := net.Listen("tcp", cfg.Address) if err != nil { return err } logger.Info("start listening at", cfg.Address) return ListenAndServe(listener, handler, closeChan) } func ListenAndServe(listener net.Listener, handler tcp.Handler, closeChan <-chan struct{}) error { go func() { <-closeChan logger.Info("shutting down...") _ = listener.Close() _ = handler.Close() }() defer func() { _ = listener.Close() _ = handler.Close() }() ctx := context.Background() var waitDone sync.WaitGroup for { conn, err := listener.Accept() if err != nil { break } logger.Info("accept link") waitDone.Add(1) go func() { defer func() { waitDone.Done() }() handler.Handle(ctx, conn) }() } // end for waitDone.Wait() return nil }