error インターフェース
CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 52/107。
Goでは、エラーはerrorと呼ばれる組み込みのインターフェースを通じて処理されます。このインターフェースは非常にシンプルで、必要とされるメソッドは1つだけです:
type error interface {
Error() string
}文字列を返す Error() メソッドを実装する任意の型は、自動的に error インターフェースを満たします。これは Go のインターフェースシステムの仕組みによるもので、明示的な宣言は必要ありません。
エラーを作成する最も一般的な方法は、errors パッケージを使用することです:
import "errors"
func Divide(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("cannot divide by zero")
}
return a / b, nil
}Goの関数は通常、最後の戻り値としてエラーを返します。エラーが発生しない場合は、nilを返します。呼び出し側は、処理を続行する前にエラーが非nilであるかどうかを確認します。
result, err := Divide(10, 0)
if err != nil {
fmt.Println("Error:", err.Error())
return
}
fmt.Println("Result:", result)また、fmt.Errorf を使用して、フォーマットされたエラーメッセージを作成することもできます:
func GetUser(id int) (string, error) {
if id <= 0 {
return "", fmt.Errorf("invalid user id: %d", id)
}
return "Alice", nil
}例外をスローするのではなくエラーを返すというこのパターンは、Goの基本です。これによりエラーハンドリングが明示的になり、問題が発生したときに何が起こるかを検討することを強制されます。これは、堅牢なオブジェクト指向コードを書くための重要な側面です。
チャレンジ
簡単Goのエラーハンドリングパターンを実演する銀行口座システムを構築しましょう。操作を検証し、問題が発生したときに意味のあるエラーを返すシンプルな口座を作成します。
コードは2つのファイルに分けて構成します:
account.go: 公開されたOwnerフィールド(string)と非公開のbalanceフィールド(float64)を持つBankAccount構造体を作成します。以下を実装してください:NewBankAccount(owner string, initialDeposit float64) (*BankAccount, error)- コンストラクタです。初回預金額が0または負の場合、"initial deposit must be positive"というメッセージを持つエラーを返します。それ以外の場合は、口座を作成して返します。Deposit(amount float64) error- 残高にお金を追加します。金額が0または負の場合、"deposit amount must be positive"というメッセージを持つエラーを返します。Withdraw(amount float64) error- 残高からお金を引き出します。金額が0または負の場合は"withdrawal amount must be positive"、残高が引き出し額より少ない場合は"insufficient funds"というメッセージを持つエラーを返します。Balance() float64- 現在の残高を返します。
main.go: 入力から口座の詳細と取引額を読み取ります。口座の作成と操作を試行します。各操作の後、成功メッセージまたはエラーメッセージのいずれかを出力します。
以下の入力が提供されます:
- 1行目: 所有者名
- 2行目: 初回預金額
- 3行目: 預金額
- 4行目: 引き出し額
各操作について、結果を出力してください:
- 口座作成後:
Account created for [Owner] with balance: $[balance]またはError: [error message] - 預金後:
Deposited successfully. New balance: $[balance]またはError: [error message] - 引き出し後:
Withdrew successfully. New balance: $[balance]またはError: [error message]
すべての残高の値は、小数点以下2桁でフォーマットしてください。口座の作成に失敗した場合は、残りの操作をスキップしてください。
例えば、Alice、100、50、200 が与えられた場合、出力は以下のようになります:
Account created for Alice with balance: $100.00
Deposited successfully. New balance: $150.00
Error: insufficient fundsまた、Bob、-50、25、10 が与えられた場合、出力は以下のようになります:
Error: initial deposit must be positiveチートシート
Goは、組み込みのerrorインターフェースを通じてエラーを処理します。これには単一のメソッドが必要です:
type error interface {
Error() string
}errorsパッケージを使用してエラーを作成します:
import "errors"
func Divide(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("cannot divide by zero")
}
return a / b, nil
}関数は、最後の戻り値としてエラーを返します。エラーが発生しない場合はnilを返します:
result, err := Divide(10, 0)
if err != nil {
fmt.Println("Error:", err.Error())
return
}
fmt.Println("Result:", result)フォーマットされたエラーメッセージにはfmt.Errorfを使用します:
func GetUser(id int) (string, error) {
if id <= 0 {
return "", fmt.Errorf("invalid user id: %d", id)
}
return "Alice", nil
}自分で試してみよう
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// 所有者の名前を読み込む
ownerName, _ := reader.ReadString('\n')
ownerName = strings.TrimSpace(ownerName)
// 初回預金額を読み込む
initialDepositStr, _ := reader.ReadString('\n')
initialDeposit, _ := strconv.ParseFloat(strings.TrimSpace(initialDepositStr), 64)
// 預金額を読み込む
depositStr, _ := reader.ReadString('\n')
depositAmount, _ := strconv.ParseFloat(strings.TrimSpace(depositStr), 64)
// 引き出し額を読み込む
withdrawStr, _ := reader.ReadString('\n')
withdrawAmount, _ := strconv.ParseFloat(strings.TrimSpace(withdrawStr), 64)
// TODO: NewBankAccount を使用して新しい銀行口座を作成する
// エラーが発生した場合は、"Error: [error message]" と出力して return する
// 成功した場合は、"Account created for [Owner] with balance: $[balance]" と出力する
// TODO: 預金額の預け入れを試みる
// エラーが発生した場合は、"Error: [error message]" と出力する
// 成功した場合は、"Deposited successfully. New balance: $[balance]" と出力する
// TODO: 引き出し額の引き出しを試みる
// エラーが発生した場合は、"Error: [error message]" と出力する
// 成功した場合は、"Withdrew successfully. New balance: $[balance]" と出力する
// fmt.Printf("%.2f", balance) を使用して、残高の値を小数点以下2桁でフォーマットすることを忘れないでください
_ = ownerName
_ = initialDeposit
_ = depositAmount
_ = withdrawAmount
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
1Go オブジェクト指向の基礎
外部ファイルGo ワークスペースとモジュールパッケージとインポート公開された名前と非公開の名前Go におけるオブジェクト指向入門クラスとしての構造体構造体へのメソッド定義ポインタレシーバと値レシーバ構造体の初期化コンストラクタ関数まとめ:簡易計算機8エラー処理とOOP
error インターフェースカスタムエラー型エラーラッピング (fmt.Errorf)センチネルエラーerrors.Is() と errors.As()Panic、Defer、Recover復習 - ファイルパーサー