>  기사  >  백엔드 개발  >  Go에서 `ioutil.ReadAll()`이 컨텍스트 기한 내에 있을 때 `json.NewDecoder().Decode()`가 컨텍스트 기한 오류를 반환하지 않는 이유는 무엇입니까?

Go에서 `ioutil.ReadAll()`이 컨텍스트 기한 내에 있을 때 `json.NewDecoder().Decode()`가 컨텍스트 기한 오류를 반환하지 않는 이유는 무엇입니까?

Barbara Streisand
Barbara Streisand원래의
2024-10-31 12:34:31463검색

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

컨텍스트 기한 내에서 json.NewDecoder().Decode()의 예기치 않은 동작

컨텍스트 기한이 설정된 Go 프로그램에서는 응답이 ioutil.ReadAll()에서 읽은 본문은 오류(context.DeadlineExceeded)를 반환할 것으로 예상됩니다. 그러나 nil을 반환하는 json.NewDecoder(resp.Body).Decode()를 사용하여 응답 본문을 읽을 때는 이 동작이 관찰되지 않습니다.

문제를 더 자세히 살펴보겠습니다.

응답에 따라 net/http 패키지는 요청을 처리하기 위해 버퍼를 사용할 수 있습니다. 이는 수신 응답 본문을 수행하기 전에 부분적으로 또는 전체적으로 읽고 버퍼링될 수 있음을 의미합니다. 따라서 만료되는 컨텍스트로 인해 본문 읽기 완료가 방해되지 않을 수 있습니다.

이를 더 명확하게 설명하기 위해 의도적으로 응답을 부분적으로 지연시키는 테스트 HTTP 서버를 시작하도록 예제를 조정했습니다.

<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>

이 테스트 서버는 ip.jsontest.com의 응답과 유사한 JSON 개체를 출력합니다. 이와 대조적으로 처음에는 본문 바이트 10개만 전달한 다음 플러시하고 나머지를 전송하기 전에 의도적으로 6초 동안 휴면 상태로 클라이언트에 만료 시간을 제공합니다.

이 서버에서 readDoesntFail()을 실행할 때 , 우리는 다음을 얻습니다:

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

이제 업데이트된 예제에서 json.Decoder.Decode()는 정보가 아직 버퍼링되지 않았기 때문에 연결에서 읽으려고 노력하며 컨텍스트 만료 시 메시지를 표시할 수 있습니다. 만료된 컨텍스트로 인해 오류가 발생했습니다.

위 내용은 Go에서 `ioutil.ReadAll()`이 컨텍스트 기한 내에 있을 때 `json.NewDecoder().Decode()`가 컨텍스트 기한 오류를 반환하지 않는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.