defer(遅延処理)Goのプログラムで結構使います

Go言語
この記事は約5分で読めます。
Go初学者
Go初学者

Go言語では絶対に忘れてはいけない処理を、あらかじめ登録しておく方法はないのですか?

この記事ではGo言語のdefer(遅延処理)について理解できます!
  • defer(遅延処理)とは
  • deferを使った簡単なプログラム例
  • deferの注意点
  • 参考としてdeferを使ったプログラム例

Go言語の制御構文に defer と呼ばれる遅延処理を行う制御構文があります。

今回は、deferについてお伝えしていきます。

もりぴ
この記事を書いた人

XHTML1.0時代にHTML&CSSを勉強した経験あり。無趣味だった私が2020年5月からプログラミング学習を開始し現在も挫折せずに趣味で学習を楽しんでいる51歳。プログラミングの楽しさをブログを通してお伝えしていきます。

もりぴをフォローする

Go言語のdefer(遅延処理)とは?

プログラムは通常、上から下へ処理(順次処理)していきますが、絶対に忘れてはいけない処理をdeferを使ってあらかじめ登録しておく制御構文です。

例えば、ファイル操作でファイルを開いたら必ず閉じなければいけません。

ファイルの閉じ忘れでプログラムが正常終了できないことを防ぐために、あらかじめファイルを開く処理のコードを書いたら、次の行に忘れずに defer を利用してファイルを閉じるコードをセットで書くことでファイルの閉じ忘れを防ぐことができます。

もりぴ
もりぴ

ファイル操作のプログラムは参考として、最後にご紹介いたします。

deferを使った簡単なプログラム例

それでは、deferを使った簡単なプログラムで実際の動きを確認してみましょう。

deferを関数で使う

// deferを関数で使う
package main

import "fmt"

func TryDefer() {
    defer fmt.Println("終わり")
    fmt.Println("始まり!")
}

func main() {
    // TryDeferを実行
    // deferで記述した処理が後から実行されるのを確認
    TryDefer()
}
// 出力結果
$ go run main.go 
始まり!
終わり

TryDefer() 関数内では、1行目に defer を使用した処理を記述しています。

出力結果を確認すると、2行目の始まり!が出力されてからdefer文が処理 終わり が出力されているのを確認できます。

もりぴ
もりぴ

これがdeferの処理を確認できる簡単なプログラムです。

deferで複数の処理をまとめる

複数の処理をあとからまとめて、deferで実行する時の例を確認しましょう。

ここでは、無名関数を使用します。

// deferで複数の処理をまとめる
package main

import "fmt"

func main() {
    // deferで複数の処理をまとめて登録
    // 無名関数を使用
    // 上から順番に処理される
    defer func() {
        fmt.Println("1")
	fmt.Println("2")
	fmt.Println("3")
    }() // 無名関数を即実行するのに () が必要

    fmt.Println("プログラムスタート!")
}
// 出力結果
$ go run main.go 
プログラムスタート!
1
2
3

無名関数を使用して defer でまとめた処理が後から順番に実行されているのを確認できます。

deferの注意点

先程、紹介したプログラムのようにdeferの処理を無名関数でまとめて処理すると上から順番にプログラムが実行されます。

しかし、defer文を複数使用した場合は注意が必要です。

実際に、プログラムで確認していきましょう。

// deferの注意点
package main

import "fmt"

func main() {
    // 複数のdeferを登録
    fmt.Println("プログラムスタート!")
    defer fmt.Println("1")
    defer fmt.Println("2")
    defer fmt.Println("3")
    fmt.Println("次にdeferの処理が始まります。")
}
// 出力結果
$ go run main.go 
プログラムスタート!
次にdeferの処理が始まります。
3
2
1

deferが下から実行されているのが確認できます。

処理の順番に問題なければいいのですが、遅延処理を上から処理を実行したい場合は、先程の無名関数でまとめたコードを記述しましょう。

【参考】deferの使用例・ファイル操作

deferの使用例としてファイル操作があげられます。

今回は参考としてプログラムをご紹介いたします。

// deferの使用例・ファイル操作
package main

import (
	"fmt"
	"os"  // ファイル操作に必要なパッケージ
)

func main() {
    // ファイル操作(ファイルを開き、閉じる時の処理にdeferを使用)
    file, err := os.Create("./hello.txt")
    // エラーハンドリング
    if err != nil {
	fmt.Println(err)
    }
    // deferで一番最後の処理を記述する
    defer file.Close()
    // ファイル操作
    file.Write([]byte("Hello World!"))
}

このプログラムは、同一フォルダ内に hello.txt があれば、 Hello World を書き込む処理をします。

最初にファイルを開く処理を記述したら defer でファイルを閉じるコードをセットで記述することでファイルの閉じ忘れを防ぐことができます。

もりぴ
もりぴ

今回はあくまでも defer の使用例ということで紹介いたしました。

【まとめ】Go言語のdeferについて

今回は、Go言語のdeferについてお伝えしてきました。

それでは、まとめに入りましょう。

Go言語のdeferで押さえておくこと!
  • deferは通常の処理が終了したあとに実行される処理を登録する
  • deferの処理をまとめて順次処理したい時は無名関数でまとめる
  • deferを複数使用する場合は、処理の順番に注意する

以上です。

いろんなプログラムに触れてくると、deferを使用することもあると思います。

deferを使う上での注意点を理解しながら、あなたのプログラムに活かしていきましょう。

comment

タイトルとURLをコピーしました