在这种情况下,Go HTTP处理程序goroutine是否会立即退出? [英] Is the Go HTTP handler goroutine expected to exit immediately in this case?

查看:305
本文介绍了在这种情况下,Go HTTP处理程序goroutine是否会立即退出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个这样的Go HTTP处理程序:

I have one Go HTTP handler like this:

mux.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
    ctx, cancel := context.WithCancel(context.Background())

    defer cancel()

    if cn, ok := w.(http.CloseNotifier); ok {
        go func(done <-chan struct{}, closed <-chan bool) {
            select {
            case <-done:
            case <-closed:
                fmt.Println("client cancelled....................!!!!!!!!!")
                cancel()
            }
        }(ctx.Done(), cn.CloseNotify())
    }

    time.Sleep(5 * time.Second)

    fmt.Println("I am still running...........")

    fmt.Fprint(w, "cancellation testing......")
})

API工作正常,然后在请求完成之前使用curl我使用 Control-C 故意终止curl命令,并在服务器端I看到客户端已取消.................... !!!!!!!!! 退出,但过了一会儿我还在运行........... 也被注销了,我以为这个goroutine会立即终止!

The API works fine, then with curl before the request finish I terminate the curl command deliberately with Control-C, and on server side I do see the client cancelled....................!!!!!!!!! get logged out, but after a while the I am still running........... get logged out also, I thought this goroutine will be terminated immediately!

那么,这是理想的行为,还是我做错了什么?

So, is this desired behaviour, or I did something wrong?

如果是预期的话,无论goroutine是什么将完成其工作,那么提前取消的重点是什么?

If it is expected, since whatever the goroutine will complete its work, then what is the point of the early cancellation?

如果我做错了什么,请帮我指出正确的方法。

If I did something wrong, please help to point me out the correct way.

推荐答案

您创建 contex.Context 可以取消,当客户端关闭连接时取消,但是你没有检查上下文,你的处理程序没有做任何不同的事情如果它被取消。上下文只有携带超时和取消信号,它没有权力也没有意图杀死/终止goroutines。 goroutines本身必须监控这些取消信号并采取行动。

You create a contex.Context that can be cancelled, which you do cancel when the client closes the connection, BUT you do not check the context and your handler does nothing differently if it is cancelled. The context only carries timeout and cancellation signals, it does not have the power nor the intent to kill / terminate goroutines. The goroutines themselves have to monitor such cancellation signals and act upon it.

所以你看到的是代码的预期输出。

So what you see is the expected output of your code.

你想要的是监控上下文,如果它被取消,从处理程序返回立即。

What you want is to monitor the context, and if it is cancelled, return "immediately" from the handler.

当然,如果你是睡觉,你无法同时监控环境。因此,请使用 time.After() ,如下例所示:

Of course if you're "sleeping", you can't monitor the context meanwhile. So instead use time.After(), like in this example:

mux.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()

    if cn, ok := w.(http.CloseNotifier); ok {
        go func(done <-chan struct{}, closed <-chan bool) {
            select {
            case <-done:
            case <-closed:
                fmt.Println("client cancelled....................!!!!!!!!!")
                cancel()
            }
        }(ctx.Done(), cn.CloseNotify())
    }

    select {
    case <-time.After(5 * time.Second):
        fmt.Println("5 seconds elapsed, client didn't close")
    case <-ctx.Done():
        fmt.Println("Context closed, client closed connection?")
        return
    }

    fmt.Fprint(w, "cancellation testing......")
})

这篇关于在这种情况下,Go HTTP处理程序goroutine是否会立即退出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆