Go の `defer` ステートメントの背後にある魔法:遅延実行の解除
Sep 07, 2025
# Go
Emily Parker
Product Engineer · Leapcell

Go の defer
ステートメントは、関数が正常にリターンするかパニックするかした瞬間に、周囲の関数が完了したときに、関数呼び出しをスケジュールすることができる、強力で慣用的な機能です。この一見単純なメカニズムは、堅牢な Go プログラミングの礎であり、リソースが適切にクリーンアップされ、重要な操作が確実に実行されるようにします。他の言語の finally
ブロックに例えられることが多いですが、独特でしばしばよりエレガントなアプローチを持っています。
defer
の解剖:仕組み
関数の実行中に defer
ステートメントに遭遇すると、defer
ステートメントで指定された関数呼び出しが即座に評価されます。これは、遅延関数への引数が、遅延関数が実際に実行されるときではなく、defer
ステートメントが実行されたときに解決されることを意味します。次に、遅延呼び出しはスタックにプッシュされます。周囲の関数がリターンすると、このスタック上の関数が後入れ先出し(LIFO)順序で実行されます。
基本的な例で説明しましょう。
package main import "fmt" func main() { defer fmt.Println("Exiting main function.") fmt.Println("Inside main function.") fmt.Println("Doing some work...") }
出力:
Inside main function.
Doing some work...
Exiting main function.
ご覧のとおり、fmt.Println("Exiting main function.")
は最初に宣言されましたが、最後に実行されました。
次に、引数の評価を検討しましょう。
package main import "fmt" func greet(name string) { fmt.Println("Hello,", name) } func main() { name := "Alice" defer greet(name) // 'name' は "Alice" として今評価される name = "Bob" // この変更は遅延呼び出しに影響しない fmt.Println("Inside main, changing name to", name) }
出力:
Inside main, changing name to Bob
Hello, Alice
これは重要な点を実証しています。name
の値 `