ループ内で遅延を使用してリソースを解放する方法: 最良のアプローチ
ループ内でデータベース クエリが関与するコンテキストでは、次のような疑問が生じます。 defer ステートメントを最適に配置して、適切なリソース解放を確保します。次のループを考えてみましょう:
for rows.Next() { fields, err := db.Query(.....) if err != nil { // ... } defer fields.Close() // do something with `fields` }
遅延配置の 2 つのオプションが現れます:
ループ本体内の遅延:
for rows.Next() { fields, err := db.Query(.....) if err != nil { // ... } // do something with `fields` } defer fields.Close()
ループ後に延期body:
for rows.Next() { fields, err := db.Query(.....) if err != nil { // ... } // do something with `fields` defer fields.Close() }
実行の遅延について
最適なアプローチを選択するには、まず遅延の動作を理解する必要があります。遅延関数は、周囲の関数が戻るまで遅延されるだけでなく、関数が例外 (パニックなど) により突然終了した場合でも実行されます。これは、例外的な状況でも確実にリソースを解放するための重要なメカニズムとして機能します。
遅延配置に関する潜在的な問題
ループ内に遅延を配置すると、ループ終了時のリソース解放が妨げられる可能性があります。 。ループ内で処理されたエラーによりループが早期に終了した場合、遅延された field.Close() 呼び出しは実行されません。
逆に、ループ本体の後に defer を配置すると、方法に関係なくリソースが解放されることが保証されます。ループが終了します。ただし、このアプローチでは、ループ全体が完了するまでリソースのクリーンアップが遅延するため、すべてのシナリオで望ましいとは限りません。
最適な解決策: 匿名または名前付き関数ラッパー
両方の問題に対処するには、リソースの割り当てと解放を匿名関数または名前付き関数内でカプセル化することが推奨される解決策です。そうすることで、関数内で defer を使用して、関数の戻り時にリソースを確実に解放できます。
例:
// Anonymous function wrapper for rows.Next() { func() { fields, err := db.Query(...) if err != nil { // Handle error and return return } defer fields.Close() // do something with `fields` }() } // Named function wrapper func foo(rs *db.Rows) { fields, err := db.Query(...) if err != nil { // Handle error and return return } defer fields.Close() // do something with `fields` } for rows.Next() { foo(rs) }
このアプローチでは、リソースがなくなるとすぐにリソースを解放できます。例外の場合でも必要です。さらに、最初のエラーでループを終了することが目的の場合は、ラッパー関数からエラーを返し、それに応じて処理できます。
func foo(rs *db.Rows) error { fields, err := db.Query(...) if err != nil { return fmt.Errorf("db.Query error: %w", err) } defer fields.Close() // do something with `fields` return nil } for rows.Next() { if err := foo(rs); err != nil { // Handle error and return return } }
Rows.Close()
Rows.Close() はエラーを返すことに注意することが重要です。このエラーを処理するには、Rows.Close() への遅延呼び出しを持つ匿名関数を使用できます:以上がGo でリソースを適切に解放するには、ループ内のどこに「defer」ステートメントを配置すればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。