Menu
Coddy logo textTech

errors.Is によるアンラップ

CoddyのGOジャーニー「論理とフロー」セクションの一部 — レッスン 40/68。

ラップされたエラーを扱う際、エラーチェーンのどこかに特定のエラーが存在するかどうかを確認する方法が必要です。errors.Is 関数はまさにこの機能を提供し、センチネルエラーが複数回ラップされている場合でも、それを特定できるようにします。

errors.Is 関数は、調査したいエラーと、探しているターゲットエラーの2つのパラメータを受け取ります。ターゲットエラーがエラーチェーンのどこかで見つかった場合、true を返します:

var ErrNotFound = errors.New("not found")

wrappedErr := fmt.Errorf("failed to load user: %w", ErrNotFound)

if errors.Is(wrappedErr, ErrNotFound) {
    fmt.Println("This is a not found error")
}

これは、Goで特定のエラーをチェックするための現代的で推奨される方法です。文字列の比較や直接的な等価性のチェックとは異なり、errors.Is はラップされたエラーに対して正しく動作し、エラーチェーンを辿って一致するものを見つけます。これにより、エラーがアプリケーションの複数のレイヤーを通過する場合でも、エラーハンドリングが堅牢で信頼性の高いものになります。

quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

challenge icon

チャレンジ

簡単

ラップされたエラーチェーン内の特定の接続エラーを識別するために、errors.Isを使用するデータベース接続監視システムを構築します。このチャレンジでは、複数のアプリケーションレイヤーを通じて追加のコンテキストでラップされている場合でも、errors.Isを使用してセンチネルエラーを検出する方法を学びます。

2つの入力を受け取ります:

  • "database_name,operation,error_type" 形式のデータベース操作の詳細を含む文字列(例:"users_db,connect,connection_timeout"
  • "service_name,retry_count" 形式のアプリケーションコンテキストを含む文字列(例:"AuthService,3"

あなたのタスクは以下の通りです:

  1. errors.New() を使用して3つのセンチネルエラーを定義します:
    • メッセージが "connection timeout"ErrConnectionTimeout
    • メッセージが "connection refused"ErrConnectionRefused
    • メッセージが "database not found"ErrDatabaseNotFound
  2. カンマで分割して最初の入力を解析し、データベース名、操作、およびエラータイプを取得します
  3. カンマで分割して2番目の入力を解析し、サービス名とリトライ回数を取得します
  4. エラータイプに基づいて元のエラーを作成します:
    • エラータイプが "connection_timeout" の場合:ErrConnectionTimeout を使用
    • エラータイプが "connection_refused" の場合:ErrConnectionRefused を使用
    • エラータイプが "database_not_found" の場合:ErrDatabaseNotFound を使用
    • その他のエラータイプの場合:errors.New("unknown database error") を使用
  5. fmt.Errorf%w を使用して、データベースレベルのラップされたエラーを作成します:"failed to [operation] database [database_name]: %w"
  6. サービスレベルのラップされたエラーを作成します:"[service_name] database operation failed after [retry_count] retries: %w"
  7. errors.Is を使用して、最終的なラップされたエラーが各センチネルエラーと一致するかどうかを確認し、結果を表示します:
    • "Checking for connection timeout: [true/false]"
    • "Checking for connection refused: [true/false]"
    • "Checking for database not found: [true/false]"
  8. エラーチェーンを表示します:
    • "Error Chain:"
    • "Original: [original_error_message]"
    • "Database level: [database_level_error_message]"
    • "Service level: [service_level_error_message]"
  9. エラー分析を表示します:
    • "Error Analysis:"
    • "Database: [database_name]"
    • "Operation: [operation]"
    • "Service: [service_name]"
    • "Retries: [retry_count]"
    • "Error type detected: [detected_error_type]" (ここで detected_error_type"Connection Timeout""Connection Refused""Database Not Found"、または "Unknown Error" のいずれか)

入力文字列をカンマで分割するために strings パッケージを、センチネルエラーと errors.Is のために errors パッケージを、そしてエラーのラップのために fmt パッケージを使用してください。このチャレンジは、errors.Is がラップされたエラーに対しても正しく機能する堅牢なエラー識別を提供し、複雑なアプリケーションにおける信頼性の高いエラーハンドリングに不可欠であることを示しています。

チートシート

errors.Is 関数は、エラーが複数回ラップされている場合でも、エラーチェーン内のどこかに特定のエラーが存在するかどうかを確認します:

var ErrNotFound = errors.New("not found")

wrappedErr := fmt.Errorf("failed to load user: %w", ErrNotFound)

if errors.Is(wrappedErr, ErrNotFound) {
    fmt.Println("This is a not found error")
}

errors.Is は、調査対象のエラーと検索対象のターゲットエラーの2つのパラメータを受け取ります。ターゲットエラーがエラーチェーン内のどこかで見つかった場合、true を返します。

これは Go で特定のエラーを確認するための現代的で推奨される方法です。文字列比較や直接的な等価性チェックとは異なり、ラップされたエラーに対しても正しく機能するためです。

自分で試してみよう

package main

import (
	"errors"
	"fmt"
	"strings"
)

func main() {
	// 入力を読み込む
	var dbOperation string
	var appContext string
	fmt.Scanln(&dbOperation)
	fmt.Scanln(&appContext)
	
	// 入力を解析する
	dbParts := strings.Split(dbOperation, ",")
	databaseName := dbParts[0]
	operation := dbParts[1]
	errorType := dbParts[2]
	
	contextParts := strings.Split(appContext, ",")
	serviceName := contextParts[0]
	retryCount := contextParts[1]
	
	// TODO: 以下にコードを記述してください
	// 1. errors.New() を使用して3つのセンチネルエラーを定義する
	// 2. エラータイプに基づいて元のエラーを作成する
	// 3. fmt.Errorf と %w を使用してデータベースレベルのラップされたエラーを作成する
	// 4. サービスレベルのラップされたエラーを作成する
	// 5. errors.Is を使用して各センチネルエラーを確認する
	// 6. 結果とエラーチェーンを表示する
	
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

論理とフローのすべてのレッスン