Menu
Coddy logo textTech

まとめ:安全な除算

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

challenge icon

チャレンジ

簡単

複数のカスタムエラー型と適切なエラーハンドリングを実装した、安全な除算を行う包括的な計算機を構築してください。このチャレンジでは、カスタムエラー型、エラーラッピング、およびエラーチェックを組み合わせて、さまざまな計算操作の失敗を適切に処理する堅牢なシステムを作成します。

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

  • "operation,num1,num2,precision" 形式の操作詳細を含む文字列(例:"divide,10,0,2"
  • "calculator_name,mode" 形式の計算機設定を含む文字列(例:"ScientificCalc,strict"

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

  1. 2つのカスタムエラー型を作成します:
    • Dividend (float64) と Divisor (float64) フィールドを持つ DivisionError 構造体
    • Field (string) と Value (float64) フィールドを持つ ValidationError 構造体
  2. DivisionError に対して、"division error: cannot divide [dividend] by [divisor]" を返す Error() string メソッドを実装します。
  3. ValidationError に対して、"validation error: invalid [field] value [value]" を返す Error() string メソッドを実装します。
  4. 最初の入力をカンマで分割して、operation、num1、num2、および precision を取得します。
  5. 2番目の入力をカンマで分割して、calculator name と mode を取得します。
  6. 文字列の数値を float64 に、precision を int に変換します。
  7. 2つの float64 パラメータを受け取り、(float64, error) を返す safeDivide 関数を作成します:
    • divisor が 0 の場合、0 と、dividend および divisor の値を持つ DivisionError を返します。
    • dividend が負の値で、mode が "strict" の場合、0 と、field が "dividend" でその dividend の値を持つ ValidationError を返します。
    • divisor が負の値で、mode が "strict" の場合、0 と、field が "divisor" でその divisor の値を持つ ValidationError を返します。
    • それ以外の場合は、除算結果と nil を返します。
  8. safeDivide の結果をラップする performCalculation 関数を作成します:
    • safeDivide がエラーを返した場合、それを "calculation failed in [calculator_name]: %w" でラップします。
    • 成功した場合は、結果と nil を返します。
  9. performCalculation を呼び出し、結果を処理します:
    • エラーがない場合:"Calculation successful: [result_formatted_to_precision_decimal_places]" を出力します。
    • エラーがある場合:"Calculation failed: [error_message]" を出力します。
  10. errors.As を使用して、ラップされたエラー内の特定の型をチェックします:
    • "Checking for division error: [true/false]" を出力します。
    • "Checking for validation error: [true/false]" を出力します。
  11. DivisionError が見つかった場合、その詳細を出力します:
    • "Division Error Details:"
    • "Dividend: [dividend]"
    • "Divisor: [divisor]"
  12. ValidationError が見つかった場合、その詳細を出力します:
    • "Validation Error Details:"
    • "Field: [field]"
    • "Value: [value]"
  13. 最終的なサマリーを表示します:
    • "Calculator Summary:"
    • "Name: [calculator_name]"
    • "Mode: [mode]"
    • "Operation: [operation]"
    • "Input: [num1] [operation_symbol] [num2]" (ここで operation_symbol は除算の場合 "/" とします)
    • "Precision: [precision] decimal places"
    • "Status: [Success/Failed]"

入力文字列をカンマで分割するには strings パッケージを、文字列を数値に変換するには strconv パッケージを、errors.As には errors パッケージを、エラーのラッピングとフォーマットには fmt パッケージを使用してください。このチャレンジは、カスタムエラー型、エラーラッピング、および適切なエラーチェックがどのように連携して、さまざまな種類の失敗に関する詳細な情報を提供する堅牢なエラーハンドリングシステムを構築するかを示しています。

自分で試してみよう

package main

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

func main() {
	// 入力を読み込む
	var operationInput string
	var settingsInput string
	fmt.Scanln(&operationInput)
	fmt.Scanln(&settingsInput)
	
	// 演算の入力を解析する (演算,数値1,数値2,精度)
	operationParts := strings.Split(operationInput, ",")
	operation := operationParts[0]
	num1, _ := strconv.ParseFloat(operationParts[1], 64)
	num2, _ := strconv.ParseFloat(operationParts[2], 64)
	precision, _ := strconv.Atoi(operationParts[3])
	
	// 設定の入力を解析する (電卓名,モード)
	settingsParts := strings.Split(settingsInput, ",")
	calculatorName := settingsParts[0]
	mode := settingsParts[1]
	
	// TODO: 以下にコードを記述してください
	// 1. Error() メソッドを持つ DivisionError と ValidationError 構造体を作成する
	// 2. safeDivide 関数を実装する
	// 3. performCalculation 関数を実装する
	// 4. performCalculation を呼び出し、結果を処理する
	// 5. errors.As を使用して特定の型のエラーを確認する
	// 6. エラーが見つかった場合は詳細を出力する
	// 7. 最終的な要約を表示する
	
}

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