コンテキスト期限内の 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(`{"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() は接続からの読み取りを試みます。これにより、コンテキストの有効期限が切れてプロンプトが表示されます。コンテキストの期限切れによるエラー。
以上がGo で ioutil.ReadAll() がコンテキスト期限内に実行するのに、 json.NewDecoder().Decode() がコンテキスト期限エラーを返さないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。