簡體   English   中英

go-gin 請求取消

[英]go-gin request cancellation

如果連接在 10 秒前關閉,如何取消進一步處理?

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()
}

您可以異步運行長時間運行的操作,並讓它在通道上發送以表示完成。

然后使用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
}

這種方法的缺點,長時間運行的操作本身會繼續執行。

當你的程序的main function 返回時,Goroutines 退出,而在實際的gin服務器中並非如此。 所以這可能不是你想要的。

在數據庫操作的情況下,大多數 API 都需要一個context.Context參數,可用於檢測請求取消。 因此,您可以將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