Go 上下文取消后函数结果的等待

Go 上下文取消后函数结果的等待,go,Go,我无法理解这个例子的逻辑 func httpDo(ctx context.context,req*http.Request,f func(*http.Response,error)error)错误{ //在goroutine中运行HTTP请求,并将响应传递给f。 c:=制造(chan错误,1) req=req.WithContext(ctx) go func(){c这并不等同于等待上下文可能会取消Do调用。的情况是这样的,你认为,这只是文档中的一个错误吗?这只是一个构思非常糟糕的示例。@Flim

我无法理解这个例子的逻辑

func httpDo(ctx context.context,req*http.Request,f func(*http.Response,error)error)错误{
//在goroutine中运行HTTP请求,并将响应传递给f。
c:=制造(chan错误,1)
req=req.WithContext(ctx)

go func(){c这并不等同于等待
上下文可能会取消
Do
调用。
的情况是这样的,你认为,这只是文档中的一个错误吗?这只是一个构思非常糟糕的示例。@Flimzy它们不是完全分开的吗?
c
是由
f
返回的,我们没有它的实现,也可能没有无论成功与否,
http.DefaultClient.Do(req)
返回后,您几乎可以做任何事情。
ctx
表示
http.DefaultClient.Do(req)
的结果,而
c
表示
f(…)的结果
f
可能会失败,而
Do
可能会顺利通过,不是吗?我认为作者最后有点懒,他说了几行`它接受一个上下文参数ctx,并在请求执行过程中关闭ctx.Done时立即返回。`=>如果关闭ctx.Done,则立即返回。但是在最后一段代码中,您怨恨,这只是因为我们知道client.Do将立即返回,它不是强保持,向它传递一个不侦听其上下文的伪函数,方案就会失败。不清楚。@mkopriva:a良好的
f()
实现将处理
ctx.Done()
即使在
Do
返回之后,当然……但这有点相切,并且你有一个其他方面的有效点。总而言之:坏例子,依我看,可能是正确的解释。但是这个例子作为客户端是令人困惑的。我相信,Do将返回上下文取消错误。@mh cbon:是的,正是。它会。看。从这个意义上说,是的。但是如果我们在运行时考虑这一点,那么程序将在结束时完成,而不是更早,超时不需要什么?此外,还可以返回CTX.Err()。不必等待@Flimzy谢谢,为新来者添加了一些,好吧,但是如果@goofinator使用当前代码,client.Do会尽快返回呢。在一些理论示例中,您可能会想到,这将保持执行,直到从c中弹出一个值。是的。这就是我的意思。我认为,在使用WithTimeout的示例中,f()也应该处理ctx,所以等待它的结果是有意义的。这在当前代码中不是必需的,但会使示例变得不清楚。IMHO@mh-我明白了。这并不明显,但是在ctx的上下文中调用了f()。这是因为f函数本身很快,但它等待http.DefaultClient.Do()完成,这是使用req调用的,之前使用req=req.WithContext(ctx)对其进行了修改。因此,一个长调用可以在内部处理Done(),并立即向通道“c”写入内容。因此,满足了客户端关于超时的期望。
func httpDo(ctx context.Context, req *http.Request, f func(*http.Response, error) error) error {
    // Run the HTTP request in a goroutine and pass the response to f.
    c := make(chan error, 1)
    req = req.WithContext(ctx)
    go func() { c <- f(http.DefaultClient.Do(req)) }()
    select {
    case <-ctx.Done():
        <-c // Wait for f to return.
        return ctx.Err()
    case err := <-c:
        return err
    }
}