简体   繁体   English

go-gin 请求取消

[英]go-gin request cancellation

How do I cancel further processing if the connection is closed before 10 seconds?如果连接在 10 秒前关闭,如何取消进一步处理?

There is c.Request.Context().Done() but coudn't find an example on how to use it.c.Request.Context().Done()但找不到有关如何使用它的示例。

func main() {
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        time.Sleep(10 * time.Second) // or some db operation
        log.Print("Processing")
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run()
}

You can run the long-running operation asynchronously and have it send on a channel to signal completion.您可以异步运行长时间运行的操作,并让它在通道上发送以表示完成。

Then you block on that completion channel and c.Request.Context().Done() with a select statement:然后使用select语句阻止该完成通道和c.Request.Context().Done()

func main() {
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        signal := make(chan struct{}, 1)

        go longRunningOperation(signal)

        select {
            case <-signal:
                close(signal) // remember to clean up after yourself
                // move on, will print "Processing"
    
            case <-c.Request.Context().Done():
                // abort
                return
        }

        log.Print("Processing")
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run()
}


func longRunningOperation(signal chan<- struct{}) {
    time.Sleep(10 * time.Second)
    signal <- struct{}{} // signal that this operation has finished
}

The disadvantage with this approach is that, as-is , the long-running operation itself would keep executing.这种方法的缺点,长时间运行的操作本身会继续执行。

Goroutines exit when the main function of your program returns, which is not the case in an actual gin server.当你的程序的main function 返回时,Goroutines 退出,而在实际的gin服务器中并非如此。 So this might not be what you want.所以这可能不是你想要的。

In the case of a database operation, most APIs require a context.Context parameter, which can be used to detect request cancellation.在数据库操作的情况下,大多数 API 都需要一个context.Context参数,可用于检测请求取消。 So you could pass the c.Request.Context() down the call chain to make sure the async long-running operation also terminates when the client disconnects.因此,您可以将c.Request.Context()传递到调用链中,以确保异步长时间运行的操作在客户端断开连接时也终止。

func Handler(c *gin.Context) {
    signal := make(chan struct{}, 1)
    go longRunningOperation(c.Request.Context(), signal)
    ...
}

func longRunningOperation(ctx context.Context, signal chan<- struct{}) {
    if err := doSomethingContext(ctx); err != nil {
        return
    }
    signal <- struct{}{} // signal that this operation has finished (successfully)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM