package middleware import ( "context" "log" "net/http" "time" "github.com/gin-gonic/gin" ) func Timeout(d time.Duration) gin.HandlerFunc { return func(c *gin.Context) { finish := make(chan struct{}, 1) panicChan := make(chan interface{}, 1) durationCtx, cancel := context.WithTimeout(c.Request.Context(), d) defer cancel() go func() { // Handle panic defer func() { if p := recover(); p != nil { panicChan <- p } }() // Run the next middleware or the business logic c.Next() finish <- struct{}{} }() select { case p := <-panicChan: // panic log.Println(p) c.Status(http.StatusInternalServerError) case <-finish: // finish normally log.Println("finish") case <-durationCtx.Done(): c.JSON(http.StatusRequestTimeout, "time out") } } }