开始请求取消

标签 go go-gin

如果连接在 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()
}

最佳答案

您可以异步运行长时间运行的操作,并将其发送到 channel 以表示完成。
然后你阻塞在那个完成 channel 和 c.Request.Context().Done()select陈述:

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

关于开始请求取消,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62740163/

相关文章:

CGO 将 Xlib XEvent 结构转换为字节数组?

go - 需要对函数进行类型断言

go - Gin 和中间件

go - 为什么 post 请求在 gin golang 中不起作用?

go - 无法从 Go 安装 Revel 框架

Go url 参数映射

golang 在子目录中找不到包 gin

go - 如何控制 gin 1.4.0+ 中缺少 URL 参数的行为?

string - Go 中如何根据分隔符的第二次出现来分割字符串?

go - 为所有用户设置转到路径时出错。