ローカル変数を使用したパニック リカバリ
Go では、defer 関数を使用したパニック リカバリにより、周囲の関数内の名前付き戻り値を変更できます。ただし、ローカル変数が戻り値として使用される場合、このメカニズムは期待どおりに機能しません。
名前付き戻り値 (result と err) が defer 関数内で変更される次の例を考えてみましょう:
<code class="go">func main() { result, err := foo() fmt.Println("result:", result) if err != nil { fmt.Println("err:", err) } } func foo() (result int, err error) { defer func() { if e := recover(); e != nil { result = -1 err = errors.New(e.(string)) } }() bar() result = 100 err = nil return } func bar() { panic("panic happened") }</code>
このコードはパニックから回復し、名前付き戻り値の結果とエラーを正しく変更します。ただし、ローカル変数が戻り値として使用される次の例を考慮してください:
<code class="go">func main() { result, err := foo() fmt.Println("result:", result) if err != nil { fmt.Println("err:", err) } } func foo() (int, error) { var result int var err error defer func() { if e := recover(); e != nil { result = -1 err = errors.New(e.(string)) } }() bar() result = 100 err = nil return result, err } func bar() { panic("panic happened") }</code>
この場合、defer 関数は result 変数と err 変数を変更できず、結果が 0 のままの予期しない出力になります。
この動作は、defer ステートメントが周囲の関数自体ではなく関数リテラルに適用されるという事実から発生します。したがって、関数リテラル内ではローカル変数 (result と err) にアクセスできません。対照的に、名前付き戻り値は、本質的に関数の先頭で初期化される変数であるため、関数リテラル内でアクセスできます。
以上がGo のパニック回復中に遅延関数はローカル変数を変更できますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。