上下文截止日期内 json.NewDecoder().Decode() 的意外行为
在设置了上下文截止日期的 Go 程序中,响应ioutil.ReadAll() 读取的正文预计会返回错误 (context.DeadlineExceeded)。然而,当使用 json.NewDecoder(resp.Body).Decode() 读取响应正文时,不会观察到这种行为,它返回 nil。
让我们更深入地研究这个问题:
根据响应,net/http 包可能会使用缓冲区来处理请求。这意味着传入的响应正文可以在您执行此操作之前部分或全部读取和缓冲。因此,过期的上下文可能不会阻止您完成正文读取。
为了更清楚地说明这一点,我们调整了一个示例来启动故意部分延迟响应的测试 HTTP 服务器:
<code class="go">ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { s := []byte(`{"ip":"12.34.56.78"}`) w.Write(s[:10]) if f, ok := w.(http.Flusher); ok { f.Flush() } time.Sleep(time.Second * 6) w.Write(s[10:]) })) defer ts.Close() url = ts.URL readDoesntFail() readFails()</code>
此测试服务器输出一个类似于 ip.jsontest.com 响应的 JSON 对象。与此相反,它最初只传递 10 个正文字节,然后刷新它们,并在传输剩余部分之前故意休眠 6 秒,为客户端提供过期时间。
当我们使用此服务器执行 readDoesntFail() 时,我们得到:
before reading response body, context error is: context deadline exceeded panic: Get "http://127.0.0.1:38230": context deadline exceeded goroutine 1 [running]: main.readDoesntFail() /tmp/sandbox721114198/prog.go:46 +0x2b4 main.main() /tmp/sandbox721114198/prog.go:28 +0x93
现在,在我们更新的示例中, json.Decoder.Decode() 会努力从连接中读取,因为信息尚未缓冲,允许上下文过期提示由于上下文过期而发生错误。
以上是为什么当 `ioutil.ReadAll()` 在 Go 的上下文截止日期内返回时,`json.NewDecoder().Decode()` 不返回上下文截止日期错误?的详细内容。更多信息请关注PHP中文网其他相关文章!