Why does `json.NewDecoder().Decode()` not return a context deadline error when `ioutil.ReadAll()` does within a context deadline in Go?

Barbara Streisand
Release: 2024-10-31 12:34:31
Original
480 people have browsed it

Why does `json.NewDecoder().Decode()` not return a context deadline error when `ioutil.ReadAll()` does within a context deadline in Go?

Unexpected Behavior of json.NewDecoder().Decode() Within Context Deadline

In Go programs with a context deadline set, the response body read by ioutil.ReadAll() is expected to return an error (context.DeadlineExceeded). However, this behavior isn't observed when reading the response body with json.NewDecoder(resp.Body).Decode(), which returns nil.

Let's delve deeper into the issue:

According to the responses, the net/http package may employ buffers to process requests. This entails that the incoming response body could be partially or entirely read and buffered prior to the time you do it. Therefore, an expiring context might not prevent you from completing the body read.

To illustrate this more clearly, we adjusted an example to launch a test HTTP server that deliberately delays the response partially:

<code class="go">ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    s := []byte(`{&quot;ip&quot;:&quot;12.34.56.78&quot;}`)
    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>
Copy after login

This test server outputs a JSON object resembling ip.jsontest.com's response. In contrast to that, it only delivers 10 body bytes initially, then flushes them, and sleeps for 6 seconds intentionally before transmitting the remainder, giving the client time to expire.

When we execute readDoesntFail() with this server, we get:

before reading response body, context error is: context deadline exceeded
panic: Get &quot;http://127.0.0.1:38230&quot;: context deadline exceeded

goroutine 1 [running]:
main.readDoesntFail()
    /tmp/sandbox721114198/prog.go:46 +0x2b4
main.main()
    /tmp/sandbox721114198/prog.go:28 +0x93
Copy after login

Now, with our updated example, json.Decoder.Decode() makes an effort to read from the connection because the information is not yet buffered, allowing the context expiration to prompt an error due to expired context.

The above is the detailed content of Why does `json.NewDecoder().Decode()` not return a context deadline error when `ioutil.ReadAll()` does within a context deadline in Go?. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!