Go json.NewDecoder().Decode() 上下文截止时间问题
在 Go 程序中,上下文截止时间提供了一种设置超时的方法某些操作。但是,用户在使用 json.NewDecoder().Decode() 时报告了意外行为。
用户关注
用户期望 json.NewDecoder()。 Decode() 以遵守为程序设置的上下文截止日期。他们观察到,正如预期的那样,使用 ioutil.ReadAll() 读取响应正文触发了上下文截止日期超出错误。然而,当他们切换到 json.NewDecoder().Decode() 时,尽管经过的时间超过了截止日期,但没有报告错误。
代码示例
ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
...
time.Sleep(time.Second * 6)
fmt.Println("before reading response body, context error is:", ctx.Err())
err = json.NewDecoder(resp.Body).Decode(ipResponse)
if err != nil {
panic(err)
}
fmt.Println("Expected panic but there was none")
Answer
行为上的差异源于 net/http 包中缓冲区的使用。根据响应的大小和配置,正文在读取之前可能会部分或完全缓冲。这意味着当使用 json.NewDecoder().Decode() 时,过期的上下文可能不会阻止缓冲数据被访问。
为了说明这一点,创建了一个测试服务器,故意延迟响应正文。它模拟了 net/http 包的部分缓冲行为。当使用此测试服务器执行 readDoesntFail() 时,确实触发了预期的上下文截止日期超出错误。
结论
在用户代码中观察到的行为突出了潜在的可能性在上下文截止日期中使用 json.NewDecoder().Decode() 的注意事项。重要的是要注意,如果响应正文很大并且已完全缓冲,则上下文截止日期可能不会按预期执行。
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3