遅延実行(defer文)
defer文は、関数の終了まで実行を延期するものです。 関数終了時に必ず行う処理を登録します。
なぜdefer文が必要か
defer文が必要な理由は次の通りです。
- 関数の終了処理を漏れなく行うため
- 関数の終了処理を複数箇所に分散させないため
- 開始処理と終了処理をセットで記載するとコードが読み易くなるため
defer文を使うかどうかでコードがどう変わるかを見てみましょう。
次のサンプルはdefer文を使わないものです。
package main
import (
"fmt"
"os"
)
func main() {
readFile("/proc/cpuinfo")
}
func readFile(filepath string) {
f, err := os.Open(filepath)
if err != nil {
fmt.Println(err)
return
}
buf := make([]byte, 64)
for {
n, err := f.Read(buf)
if n == 0 {
break
}
if err != nil {
fmt.Println(err)
f.Close()
return
}
fmt.Print(string(buf[:n]))
}
fmt.Println("readFile関数は正常に処理しました。")
f.Close()
}
defer文を使うと次の通りです。defer文の書き方は以降で説明します。
package main
import (
"fmt"
"os"
)
func main() {
readFile("/proc/cpuinfo")
}
func readFile(filepath string) {
f, err := os.Open(filepath)
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
buf := make([]byte, 64)
for {
n, err := f.Read(buf)
if n == 0 {
break
}
if err != nil {
fmt.Println(err)
return
}
fmt.Print(string(buf[:n]))
}
fmt.Println("readFile関数は正常に処理しました。")
}
defer文の書き方
キーワードdefer
を使って、関数終了時に実行する式を追加できます。
defer文に書いた関数の引数は即時評価されますが、defer文に書いた関数の実行は、外側の関数が終了する直前まで延期されます。
複数追加した場合、最後に追加されたものから順に実行されます。
func main() {
fmt.Println(1)
i := 11
// 引数は即時評価
defer fmt.Println(i)
i = 111
defer fmt.Println(12)
fmt.Println(2)
}
// 実行結果:
// 1
// 2
// 12
// 11