以下是示例

package main

import (
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"time"
)

// TimeoutMiddleware wraps the request context with a timeout
func TimeoutMiddleware(timeout time.Duration) func(c *gin.Context) {
	return func(c *gin.Context) {
		// wrap the request context with a timeout
		ctx, cancel := context.WithTimeout(c.Request.Context(), timeout)

		defer func() {
			// check if context timeout was reached
			if ctx.Err() == context.DeadlineExceeded {
				// write response and abort the request
				c.Writer.WriteHeader(http.StatusGatewayTimeout)
				c.Abort()
			}
			//c.JSON(http.StatusOK, "请求超时")
			cancel()
		}()

		// replace request with context wrapped request
		c.Request = c.Request.WithContext(ctx)
		c.Next()
	}
}

// timedHandler 模拟实际项目中的handler
func timedHandler(duration time.Duration) func(c *gin.Context) {
	return func(c *gin.Context) {
		// get the underlying request context
		ctx := c.Request.Context()
		// create the response data type to use as a channel type
		type responseData struct {
			status int
			body   map[string]interface{}
		}
		// create a done channel to tell the request it's done
		doneChan := make(chan responseData)
		// here you put the actual work needed for the request
		// and then send the doneChan with the status and body
		// to finish the request by writing the response
		go func() {
			time.Sleep(duration)
			doneChan <- responseData{
				status: 200,
				body:   gin.H{"hello": "world"},
			}
		}()
		// non-blocking select on two channels see if the request
		// times out or finishes
		select {
		// if the context is done it timed out or was cancelled
		// so don't return anything
		case <-ctx.Done():
			fmt.Println(ctx.Err())
			return
			// if the request finished then finish the request by
			// writing the response
		case res := <-doneChan:
			c.JSON(res.status, res.body)
		}
	}
}

func main() {
	engine := gin.New()
	engine.Use(TimeoutMiddleware(time.Second * 2))
	engine.GET("/normal", timedHandler(time.Second))
	engine.GET("/exceed", timedHandler(time.Second*5))
	log.Fatal(engine.Run(":8088"))
}
curl localhost:8089/normalcurl localhost:8089/exceed