11

http.Client 中设置的超时和请求上下文中设置的超时有什么区别?

我已经看到了 2 种在 http 客户端中设置超时的方法。

第一的:

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "http://localhost:8080", nil)

第二:

client := http.Client{
    Timeout: 2 * time.Second,
}
resp, err := client.Do(req)
if err != nil {
    panic(err)
}

什么时候使用一个而不是另一个?

4

2 回答 2

8

两者都可以实现相同的目的,即由于超时而终止请求。

但是使用上下文是为这项任务而设计的首选方式。在将上下文添加到 Go 之前存在字段超时。您必须在创建请求时选择一个超时,因为请求将选择要应用的较小超时,从而使其他超时无用。在这种情况下,最好的方法是使用上下文超时,因为您可以更好地控制它,如果您想通过逻辑决策取消请求,您可以使用取消而不指定超时。使用上下文,您还可以通过它传递任何描述请求范围值的值。

使用上下文是特定于请求的,而使用客户端超时可能会应用于传递给Do客户端方法的所有请求。如果您想将截止日期/超时专门用于每个请求,则使用上下文,否则如果您希望每个出站请求有 1 个超时,那么使用客户端超时就足够了。

您还可以在此处阅读有关它在 Go 中跟踪 HTTP 请求时指定超时

于 2020-10-01T00:03:11.953 回答
3

通常,当我们只想为 http 请求设置超时时,我们会使用此方法

client := http.Client{
    Timeout: 2 * time.Second,
}
resp, err := client.Do(req)
if err != nil {
    panic(err)
}

我认为问题是我们什么时候应该使用上下文,如果你去文档你会发现

包上下文定义了 Context 类型,它携带跨越 API 边界和进程之间的截止日期、取消信号和其他请求范围的值。

因此,假设您有一个 API 需要在一段时间内做出响应,并且您需要一种方法来跟踪它创建的所有 go 例程,并希望同时向它们发出信号以停止;这是使用上下文并将其传递给由一个 API 调用创建的所有 go 例程的用例,并且很容易知道上下文何时过期以及每个人何时需要停止工作。

尽管您执行 http 请求的方式会起作用,但创建一个对特定请求明确的上下文并没有多大意义,除非假设您的请求在 goroutine 中运行并且您需要传递取消信号,因为其他一些执行后收到的输入。

理想情况下,在大多数情况下,上下文用于确定您需要发出信号的请求/ goroutine 链的范围。

您应该阅读本文以更清楚地了解何时使用上下文 https://blog.golang.org/context

于 2020-09-30T04:22:55.033 回答