導入
ファイルを開いたら閉じる、という「最後に必ずやりたい後始末」を書き忘れないための仕組みが defer(ディファー) です。
説明
defer を付けた関数呼び出しは、いまの関数が終わる直前に必ず実行されます。
package main
import "fmt"
func main() {
defer fmt.Println("3. 後始末(defer)")
fmt.Println("1. 処理を開始")
fmt.Println("2. 処理を実行")
// main が終わる直前に defer が動く
}
実行結果:
1. 処理を開始
2. 処理を実行
3. 後始末(defer)
defer は書いた場所で実行されず、関数の出口まで先送りされます。ファイルを開いた直後に defer file.Close() と書いておけば、途中でどこから return しても閉じ忘れません。実務では次のようなパターンで多用します。
f, err := os.Open("data.txt")
if err != nil {
return err
}
defer f.Close() // この関数を抜けるとき、必ず閉じる
やってみよう
defer を付けた行が、書いた位置ではなく最後に実行される点を出力の順番で確かめましょう。「開く直後に閉じる予約をする」ことで、後始末の書き忘れを防げます。
演習
defer をもう1行足して、後から予約したものが先に実行されること(後入れ先出し)を確かめてください。追加するのは 4. さらに後始末(defer) の表示です。
ヒント1を見る
既存の defer のすぐ下に、もう1つ defer fmt.Println("4. さらに後始末(defer)") を書きます。
ヒント2を見る
defer は積み上げた順の逆に実行されます。あとから予約した「4.」が先に、最初に予約した「3.」が最後に出ます。