ホームページ >バックエンド開発 >Golang >Golang関数におけるdeferキーワードの例外処理方法

Golang関数におけるdeferキーワードの例外処理方法

WBOY
WBOYオリジナル
2023-05-17 08:22:571745ブラウズ

Golang は比較的新興のオープンソースで高性能なプログラミング言語であり、その機能の 1 つは関数の defer キーワードです。このキーワードを使用すると、リソースのクリーンアップやログ出力など、関数の終了前に必要な操作を実行できます。また、例外を処理するためにも使用できるため、コードがより堅牢で信頼性が高くなります。この記事では、読者がこの機能をより上手に使用できるように、例外処理における Golang 関数の defer キーワードの適用について詳しく説明します。

1. defer の使用方法

Golang では、defer キーワードを使用して、関数の終了後に実行される関数呼び出しを定義できます。 defer の特別な点は、関数の途中で例外が発生したかどうかに関係なく、関数が戻る前に実行されることです。例:

func demo() {
    defer fmt.Println("defer end.")
    fmt.Println("normal flow.")
}

上記のコードでは、print ステートメント「normal flow.」が defer ステートメント「defer fmt.Println("defer end.")」の前に実行されます。

さらに、関数内で複数の defer ステートメントが使用されている場合、それらの実行順序はスタック上にあり、後で定義された defer ステートメントが最初に実行されます。例:

func demo() {
    defer fmt.Println("defer 1.")
    defer fmt.Println("defer 2.")
    fmt.Println("normal flow.")
}

上記のコードでは、ステートメント「normal flow.」が最初に出力され、次に「defer 2.」、最後に「defer 1.」が出力されます。

2. 例外処理の遅延

通常の使用に加えて、遅延はコード内の例外を処理するためにも使用できます。例外とは、プログラムの実行中に発生するエラーであり、不正な入力、論理エラー、システム エラーなど、さまざまな理由が考えられます。 Golang では、panic/defer/recover の 3 つのキーワードを通じて例外を処理できます。その中で、panic は例外を引き起こし、recover は例外をキャッチして処理し、defer は例外が処理された後に必要なクリーンアップ操作を実行します。以下は、panic/defer/recover の使用法を示す実践的な例です。

func catchError() {
    defer func() {
        if err := recover(); err != nil {
            fmt.Println("recovered from: ", err)
        }
    }()
    fmt.Println("start")
    panic("error occurs!")
    fmt.Println("end")
}

上記のコードでは、catchError 関数を呼び出し、最初にステートメント "start" を出力し、次に、panic を使用してエラーを引き起こします。例外がスローされ、「エラーが発生しました!」と出力されます。この時点で、プログラムは中断され、catchError 関数で定義された遅延に入ります。この defer には、現在例外をキャッチしたかどうかを判定する if 文があり、例外をキャッチした場合は fmt.Println が呼び出されて「recovered from:」され、例外情報 err が出力されます。

この例は、関数内で例外が発生したときに、Golang の Panic/defer/recover キーワードを使用して、それに応じてプログラムを処理できることを示しています。 defer キーワードはどのような状況でも実行されるため、ファイルを閉じる、リソースを解放するなど、プログラムで例外が発生したときに defer を使用して必要なクリーンアップ操作を実行できます。

3. defer に関する注意事項

defer キーワードを使用する場合は、次の点に注意する必要があります:

  1. ループ構造内の defer の場合、特別な実行のタイミングに注意してください。
func testLoop() {
    for i := 0; i < 5; i++ {
        defer fmt.Println("defer: ",i)
    }
    fmt.Println("test loop done.")
}

上記のコードでは、遅延テストにループ構造を使用しています。ループ内で使用されているリソースを解放できるように、各ループの最後に最初に defer ステートメントが実行されるようにします。ただし、上記のコードでは、defer ステートメントが LIFO (後入れ先出し) で実行されるため、最終的に出力されるのは、「defer: 4, defer: 3, ..., defer: 0」ではなく「testloopned.」です。 .「どうやって解決するの? 1 つの方法は、コードを次のように変更することです:

func testLoop() {
    for i := 0; i < 5; i++ {
        defer func(i int) {
            fmt.Println("defer: ", i)
        }(i)
    }
    fmt.Println("test loop done.")
}

この方法では、defer ステートメントにクロージャを追加し、現在の i 値をクロージャ関数に直接渡し、後で実行できるようにします。正しい値を呼び出します。ご覧のとおり、コードをこのように変更した後、「テスト ループが完了しました。」と「defer: 4, defer: 3, ..., defer: 0.」が正常に出力されました。

  1. 遅延を使用する場合は、それがもたらすパフォーマンスへの影響にも注意する必要があります。各 defer ステートメントによりプログラムのオーバーヘッドが増加するためです。したがって、プログラムまたは関数で遅延を使用する回数は、プログラムのパフォーマンスへの影響を避けるために、妥当な範囲内で制御する必要があります。
  2. defer ステートメント内のパラメータは定義時に計算されるため、変更しないでください。この場合、予期しない結果が生じる可能性があります。
  3. キーワード defer ステートメントに go 関数が含まれている場合、ゴルーチンは関数の実行の最後に呼び出され、main 関数の実行には影響しません。

4. 概要

Golang では、defer キーワードは非常に重要な機能です。ファイルを閉じる、リソースを解放するなど、関数のクリーンアップ操作を実行するために使用できます。さらに、関数内で例外が発生した場合、defer ステートメントは例外をキャッチして処理する上で一定の役割を果たすこともできます。 defer を使用する場合は、プログラム開発でこの機能を最大限に活用し、プログラムをより堅牢で信頼性の高いものにするために、その使い方をマスターし、関連する予防措置に注意を払う必要があります。

以上がGolang関数におけるdeferキーワードの例外処理方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。