Menu
Coddy logo textTech

errors.As によるアンラップ

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

errors.Is はエラーチェーン内の特定のエラー値を識別するのに役立ちますが、カスタムエラータイプの実際のフィールドやデータにアクセスする必要がある場合もあります。errors.As 関数は、チェーン内で特定の型に一致する最初のエラーを見つけ、検査のためにそれを抽出することで、この機能を提供します。

errors.As 関数は、調査対象のエラーと、ターゲットとなるエラー型の変数へのポインタという2つのパラメータを受け取ります。チェーン内に一致するエラー型が見つかった場合、その変数にそのエラーを代入し、true を返します。

var validationErr ValidationError
if errors.As(wrappedErr, &validationErr) {
    fmt.Printf("Field: %s, Message: %s\n", validationErr.Field, validationErr.Message)
}

これは、追加のコンテキストを含むカスタムエラー型を扱う場合に特に強力です。等価性のみをチェックする errors.Is とは異なり、errors.As は実際のエラーインスタンスを抽出するため、そのフィールドやメソッドにアクセスできるようになります。これにより、複雑なアプリケーションにおけるエラーハンドリングがより洗練され、情報量の多いものになります。

quiz icon腕試し

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

quiz icon腕試し

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

quiz icon腕試し

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

challenge icon

チャレンジ

簡単

errors.As を使用して、ラップされたエラーチェーンからカスタムエラー型を抽出および調査する API エラー処理システムを構築します。このチャレンジでは、追加のコンテキストでラップされている場合でも、errors.As を使用して特定のカスタムエラー型のフィールドやデータにアクセスする方法を学びます。

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

  • "endpoint,method,error_code,error_field" 形式の API リクエストの詳細を含む文字列(例:"/users,POST,400,email"
  • "service_name,request_id" 形式のシステムコンテキストを含む文字列(例:"UserAPI,req_12345"

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

  1. 3つのフィールドを持つ APIError 構造体というカスタムエラー型を作成します:
    • Code (int) - HTTP ステータスコード
    • Field (string) - エラーの原因となったフィールド
    • Message (string) - エラーの説明
  2. "API error [code]: [message] (field: [field])" を返す APIErrorError() string メソッドを実装します。
  3. 最初の入力をカンマで分割して、エンドポイント、メソッド、エラーコード、エラーフィールドを取得します。
  4. 2番目の入力をカンマで分割して、サービス名とリクエスト ID を取得します。
  5. エラーコードの文字列を整数に変換します。
  6. エラーコードに基づいて APIError インスタンスを作成します:
    • コードが 400 の場合:メッセージ "invalid request data"
    • コードが 401 の場合:メッセージ "authentication required"
    • コードが 404 の場合:メッセージ "resource not found"
    • コードが 500 の場合:メッセージ "internal server error"
    • その他のコードの場合:メッセージ "unknown error"
  7. fmt.Errorf%w を使用して、エンドポイントレベルのラップされたエラーを作成します:"[method] [endpoint] failed: %w"
  8. サービスレベルのラップされたエラーを作成します:"[service_name] request [request_id] failed: %w"
  9. errors.As を使用してラップされたエラーチェーンから APIError を抽出し、抽出結果を表示します:
    • 抽出に成功した場合:"API error extracted successfully"
    • 抽出に失敗した場合:"Failed to extract API error"
  10. 抽出に成功した場合は、抽出されたエラーの詳細を表示します:
    • "Extracted Error Details:"
    • "Code: [code]"
    • "Field: [field]"
    • "Message: [message]"
    • "Full error: [full_error_message_from_Error_method]"
  11. 完全なエラーチェーンを表示します:
    • "Error Chain:"
    • "Original: [original_api_error_message]"
    • "Endpoint level: [endpoint_level_error_message]"
    • "Service level: [service_level_error_message]"
  12. 最終的な分析を表示します:
    • "Error Analysis:"
    • "Service: [service_name]"
    • "Request ID: [request_id]"
    • "Endpoint: [method] [endpoint]"
    • "HTTP Status: [code]"
    • "Problem Field: [field]"
    • "Error Category: [error_category]"error_category は、コード 400-499 の場合は "Client Error"、コード 500-599 の場合は "Server Error"、その他のコードの場合は "Unknown" とします)

strings パッケージを使用して入力文字列をカンマで分割し、strconv パッケージを使用してエラーコード文字列を整数に変換し、errors パッケージを errors.As に、fmt パッケージをエラーのラッピングに使用します。このチャレンジでは、errors.As を使用してラップされたエラーチェーン内のカスタムエラー型の特定のフィールドやメソッドにアクセスし、高度なエラー処理と分析を可能にする方法を示します。

チートシート

errors.As 関数は、エラーチェーンから特定のエラー型を抽出し、カスタムエラーのフィールドやメソッドへのアクセスを可能にします。

errors.As は、調査対象のエラーと、ターゲットとなるエラー型の変数へのポインタという2つのパラメータを受け取ります。

var validationErr ValidationError
if errors.As(wrappedErr, &validationErr) {
    fmt.Printf("Field: %s, Message: %s\n", validationErr.Field, validationErr.Message)
}

同等性のみをチェックする errors.Is とは異なり、errors.As は実際のエラーインスタンスを抽出するため、そのフィールドやメソッドにアクセスして、より高度なエラーハンドリングを行うことができます。

自分で試してみよう

package main

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

func main() {
	// 入力を読み込む
	var apiDetails string
	var systemContext string
	fmt.Scanln(&apiDetails)
	fmt.Scanln(&systemContext)
	
	// 入力を解析する
	apiParts := strings.Split(apiDetails, ",")
	endpoint := apiParts[0]
	method := apiParts[1]
	errorCodeStr := apiParts[2]
	errorField := apiParts[3]
	
	contextParts := strings.Split(systemContext, ",")
	serviceName := contextParts[0]
	requestID := contextParts[1]
	
	// エラーコードを整数に変換する
	errorCode, _ := strconv.Atoi(errorCodeStr)
	
	// TODO: 以下にコードを記述してください
	// 1. Code、Field、Messageフィールドを持つAPIError構造体を作成する
	// 2. APIErrorのError()メソッドを実装する
	// 3. エラーコードに基づいてAPIErrorインスタンスを作成する
	// 4. ラップされたエラー(エンドポイントレベルおよびサービスレベル)を作成する
	// 5. errors.Asを使用して、ラップされたエラーチェーンからAPIErrorを抽出する
	// 6. 抽出結果とエラーの詳細を表示する
	// 7. エラーチェーンと最終的な分析を表示する
	
}
quiz icon腕試し

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

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