ホームページ  >  記事  >  バックエンド開発  >  http `client.Do(...)` によって `response` が返される `ReadAll(response.Body)` を試行すると、Goroutine でリークが発生します。

http `client.Do(...)` によって `response` が返される `ReadAll(response.Body)` を試行すると、Goroutine でリークが発生します。

PHPz
PHPz転載
2024-02-09 23:06:18332ブラウズ

当尝试 `ReadAll(response.Body)` 时,goroutine 泄漏,其中 `response` 由 http `client.Do(...)` 返回

#php エディター Baicao は、プログラミングの問題を解決する際によくある goroutine リークを発見しました。 `ReadAll(response.Body)` を使用しようとすると、返される `response` オブジェクトは、`http` パッケージの `client.Do(...)` メソッドによって返されます。ただし、この操作ではゴルーチンのリーク問題が発生する可能性があります。これを回避するには、http 応答を適切に処理するための対策を講じる必要があります。

質問の内容

この質問は、http メソッド呼び出し後に応答本文からすべてのバイトが読み取られるという、非常に一般的なシナリオからのものです。

https://github.com/uber-go/goleak の助けを借りて、興味深い goroutine リークを発見しました。

問題を実証するには、go test を使用して次のテスト コードを実行します。その結果、予期しない goroutine が見つかりました:

リーリー

完全なテスト出力:

リーリー

この問題の解決方法を知っている人はいますか?

###ありがとう!

解決策

Goでは、

http.ClientTransport(http.RoundTripperインターフェース)を使用します。 http.Transport がデフォルトの実装です。デフォルトの http.Transfer は、何らかの理由でアクティブまたはアイドル状態のままの接続を保持する接続プールを維持します。

基本的に必要なのは、

goleak.Verify を呼び出すときに、プール内に接続がないことを確認することだけです*

これは次の方法で実行できます:

  1. リクエストを実行する前に、すべての http クライアントのキープアライブを無効にします:
    クライアント := http.Client{トランスポート: &http.Transport{DisableKeepAlive: true}}
  2. goleak.Verify*: を呼び出す前にアイドル状態の接続を閉じてください。 client.CloseIdleConnections()
    // Go 1.12 以降で利用可能

以上がhttp `client.Do(...)` によって `response` が返される `ReadAll(response.Body)` を試行すると、Goroutine でリークが発生します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はstackoverflow.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。