ملخص - القسمة الآمنة
جزء من قسم Logic & Flow في رحلة GO على Coddy — الدرس 44 من 68.
التحدي
سهلقم ببناء آلة حاسبة رياضية شاملة تنفذ عملية القسمة الآمنة مع أنواع أخطاء مخصصة متعددة ومعالجة صحيحة للأخطاء. يجمع هذا التحدي بين أنواع الأخطاء المخصصة، وتغليف الأخطاء (error wrapping)، وفحص الأخطاء لإنشاء نظام قوي يتعامل مع حالات فشل العمليات الرياضية المختلفة بسلاسة.
ستتلقى مدخلين:
- سلسلة نصية تحتوي على تفاصيل العملية بتنسيق
"operation,num1,num2,precision"(على سبيل المثال،"divide,10,0,2") - سلسلة نصية تحتوي على إعدادات الآلة الحاسبة بتنسيق
"calculator_name,mode"(على سبيل المثال،"ScientificCalc,strict")
مهمتك هي:
- إنشاء نوعين من الأخطاء المخصصة:
- هيكل
DivisionErrorمع حقولDividend(float64) وDivisor(float64) - هيكل
ValidationErrorمع حقولField(string) وValue(float64)
- هيكل
- تنفيذ تابع
Error() stringللهيكلDivisionErrorبحيث يعيد:"division error: cannot divide [dividend] by [divisor]" - تنفيذ تابع
Error() stringللهيكلValidationErrorبحيث يعيد:"validation error: invalid [field] value [value]" - تحليل المدخل الأول عن طريق التقسيم عند الفواصل للحصول على operation و num1 و num2 و precision
- تحليل المدخل الثاني عن طريق التقسيم عند الفواصل للحصول على calculator name و mode
- تحويل الأرقام النصية إلى float64 والدقة (precision) إلى int
- إنشاء دالة
safeDivideتأخذ معاملين من نوع float64 وتعيد (float64, error):- إذا كان المقسوم عليه (divisor) هو 0، فقم بإعادة 0 و
DivisionErrorمع قيم المقسوم والمقسوم عليه - إذا كان المقسوم (dividend) سالباً وكان الوضع (mode) هو
"strict"، فقم بإعادة 0 وValidationErrorمع الحقل"dividend"وقيمة المقسوم - إذا كان المقسوم عليه (divisor) سالباً وكان الوضع (mode) هو
"strict"، فقم بإعادة 0 وValidationErrorمع الحقل"divisor"وقيمة المقسوم عليه - خلاف ذلك، قم بإعادة نتيجة القسمة و nil
- إذا كان المقسوم عليه (divisor) هو 0، فقم بإعادة 0 و
- إنشاء دالة
performCalculationتقوم بتغليف نتيجةsafeDivide:- إذا أعادت
safeDivideخطأً، فقم بتغليفه بـ:"calculation failed in [calculator_name]: %w" - إذا نجحت، فقم بإعادة النتيجة و nil
- إذا أعادت
- استدعاء
performCalculationوالتعامل مع النتيجة:- في حالة عدم وجود خطأ: اطبع
"Calculation successful: [result_formatted_to_precision_decimal_places]" - في حالة وجود خطأ: اطبع
"Calculation failed: [error_message]"
- في حالة عدم وجود خطأ: اطبع
- استخدام
errors.Asللتحقق من أنواع أخطاء محددة في الخطأ المغلف:- اطبع
"Checking for division error: [true/false]" - اطبع
"Checking for validation error: [true/false]"
- اطبع
- إذا تم العثور على
DivisionError، اطبع تفاصيله:"Division Error Details:""Dividend: [dividend]""Divisor: [divisor]"
- إذا تم العثور على
ValidationError، اطبع تفاصيله:"Validation Error Details:""Field: [field]""Value: [value]"
- عرض ملخص نهائي:
"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 من أجل errors.As، وحزمة 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. قم بإنشاء هياكل DivisionError و ValidationError مع دوال Error()
// 2. قم بتنفيذ دالة safeDivide
// 3. قم بتنفيذ دالة performCalculation
// 4. قم باستدعاء performCalculation ومعالجة النتائج
// 5. استخدم errors.As للتحقق من أنواع أخطاء محددة
// 6. اطبع تفاصيل الخطأ في حال العثور عليه
// 7. اعرض الملخص النهائي
}جميع دروس Logic & Flow
1تدفق التحكم المتقدم
جملة Switch مع `fallthrough`الخروج من الحلقات المتداخلةالاستمرار في حلقة محددةجملة `goto`ملخص - التحكم المتقدم في الحلقات7معالجة الأخطاء بعمق
أنواع الأخطاء المخصصةتغليف الأخطاء باستخدام `%w`فك التغليف باستخدام `errors.Is`فك التغليف باستخدام `errors.As`فهم `panic`استخدام `recover`ملخص - القسمة الآمنة2الـ Structs والميثودز (Methods)
تعريف الـ Methods على الـ Structsالـ Value Receiversالـ Pointer Receiversاختيار الـ Receiversالـ Methods مقابل الـ Functionsملخص - سلوك الـ Struct5تعمق في الـ Maps
Maps من نوع Structsالـ Pointers كقيم في الـ Mapsالتحقق من الـ Nil Mapsمقارنة الـ Mapsمراجعة - عداد تكرار الكلمات3الواجهات (الأساسيات)
ما هي الواجهة؟تعريف الواجهةتطبيق الواجهةاستخدام أنواع الواجهاتالواجهة الفارغةتأكيدات النوع (Type Assertions)تبديل النوع (Type Switch)ملخص - الأشكال والسلوكيات