Go言語で例外処理を実装する方法

Go言語で例外処理を実装する方法

Go言語では、従来の例外処理機構(例:try-catchブロック)を使用する代わりに、エラーハンドリングに関する独自のアプローチを採用しています。
Goのエラーハンドリングは主にerror型を利用し、エラーが発生した際にはそのエラーを呼び出し元に返すという形式です。
この方法は、明示的にエラーチェックを行い、エラーが発生した場合には適切な処理を行うことを推奨しています。

まず、Go言語の関数はエラーを返すことができます。
エラーが発生する可能性のある関数の定義では、error型を返り値に追加します。
以下に、エラーハンドリングの基本的な実装方法を示します。

package main

import (
  "fmt"
  "errors"
)

// エラーを返す関数の例
func divide(a, b int) (int, error) {
  if b == 0 {
    // エラーが発生した場合、エラーメッセージを含むerror型を返す
    return 0, errors.New("division by zero")
  }
  return a / b, nil
}

func main() {
  result, err := divide(10, 0)
  if err != nil {
    // エラーが発生した場合、エラーメッセージを表示する
    fmt.Println("Error:", err)
    return
  }
  fmt.Println("Result:", result)
}

この例では、divide関数が2つの整数を受け取り、除算を行います。
除数が0の場合、エラーを生成し、そのエラーを返します。
main関数では、divide関数を呼び出し、エラーが発生した場合にはエラーメッセージを表示し、プログラムを終了させます。

Go言語には、エラー処理のためにdefer、panic、recoverという3つのキーワードも用意されています。
これらを組み合わせることで、より柔軟なエラーハンドリングが可能です。

1. defer:
関数が終了する直前に実行される処理を指定します。
リソースのクリーンアップなどに使用されます。
2. panic:
エラーが致命的であると判断された場合に、実行中の処理を中断し、スタックトレースを表示するために使用されます。
3. recover:
panicによって中断された処理を回復するために使用されます。
defer内で呼び出すことで、panicから回復できます。

以下に、panicとrecoverを使用したエラーハンドリングの例を示します。

package main

import (
  "fmt"
)

// パニックを引き起こす関数の例
func mayPanic() {
  defer func() {
    if r := recover(); r != nil {
      // パニックから回復し、エラーメッセージを表示する
      fmt.Println("Recovered from panic:", r)
    }
  }()
  panic("something went wrong")
}

func main() {
  mayPanic()
  fmt.Println("After recover")
}

この例では、mayPanic関数内でpanicを発生させ、その後defer内でrecoverを使ってパニックから回復します。
recoverがパニックを検出すると、プログラムはエラーメッセージを表示し、正常な状態に戻ります。

Go言語のエラーハンドリングは、エラーの発生と処理を明示的に行うため、プログラムの動作が明確であり、エラーチェックを忘れることが少なくなります。
しかし、panicとrecoverは予期しないエラー処理の最後の手段として使うべきであり、通常のエラーハンドリングにはerror型を利用することが推奨されます。