Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

تغليف الأخطاء باستخدام `%w`

جزء من قسم Logic & Flow في رحلة GO على Coddy — الدرس 39 من 68.

عندما تحدث أخطاء في تطبيقك، فإنها غالباً ما تحتاج إلى سياق إضافي أثناء انتقالها عبر طبقات مختلفة من الكود الخاص بك. توفر Go آلية قوية لذلك من خلال تغليف الأخطاء (error wrapping) باستخدام فعل التنسيق %w مع fmt.Errorf.

يسمح لك تغليف الأخطاء (Error wrapping) بإضافة معلومات سياقية إلى خطأ موجود مع الحفاظ على الخطأ الأصلي تحته. يؤدي هذا إلى إنشاء سلسلة أخطاء تحافظ على السجل الكامل لما حدث بشكل خاطئ:

originalErr := errors.New("file not found")
wrappedErr := fmt.Errorf("failed to load config: %w", originalErr)

إنّ واصف التنسيق %w خاص - فهو يخبر fmt.Errorf بتغليف الخطأ بدلاً من مجرد تحويله إلى سلسلة نصية. وهذا يحفظ الخطأ الأصلي بحيث يمكن فحصه لاحقاً باستخدام دوال مثل errors.Is و errors.As.

هذا النمط ذو قيمة خاصة في التطبيقات الكبيرة حيث قد يمر الخطأ عبر وظائف متعددة، تضيف كل منها سياقها الخاص. على سبيل المثال، قد يتم تغليف خطأ في الاتصال بقاعدة البيانات بعبارة "failed to connect to database"، ثم يتم تغليفه مرة أخرى بعبارة "unable to start server"، مما يخلق مساراً واضحاً لما حدث وأين.

quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

challenge icon

التحدي

سهل

قم ببناء نظام معالجة ملفات يقوم بتغليف الأخطاء بمعلومات سياقية أثناء انتقالها عبر طبقات مختلفة من تطبيقك. يوضح هذا التحدي كيفية استخدام فعل التنسيق %w مع fmt.Errorf لإنشاء سلاسل أخطاء تحافظ على الخطأ الأصلي مع إضافة سياق ذي معنى.

ستتلقى مدخلين:

  • سلسلة نصية تحتوي على تفاصيل عملية الملف بتنسيق "filename,operation,status" (على سبيل المثال، "config.json,read,permission_denied")
  • سلسلة نصية تحتوي على سياق النظام بتنسيق "service_name,component" (على سبيل المثال، "UserService,ConfigLoader")

مهمتك هي:

  1. تحليل المدخل الأول عن طريق التقسيم عند الفواصل للحصول على اسم الملف (filename)، والعملية (operation)، والحالة (status)
  2. تحليل المدخل الثاني عن طريق التقسيم عند الفواصل للحصول على اسم الخدمة (service name) والمكون (component)
  3. إنشاء خطأ أصلي بناءً على الحالة باستخدام errors.New():
    • إذا كانت الحالة "permission_denied": "permission denied"
    • إذا كانت الحالة "not_found": "file not found"
    • إذا كانت الحالة "corrupted": "file corrupted"
    • لأي حالة أخرى: "unknown error"
  4. إنشاء خطأ مغلف على مستوى الملف باستخدام fmt.Errorf مع %w: "failed to [operation] file [filename]: %w"
  5. إنشاء خطأ مغلف على مستوى المكون: "[component] error: %w"
  6. إنشاء خطأ مغلف على مستوى الخدمة: "[service_name] operation failed: %w"
  7. عرض سلسلة الأخطاء عن طريق طباعة كل مستوى:
    • "Original error: [original_error_message]"
    • "File level: [file_level_error_message]"
    • "Component level: [component_level_error_message]"
    • "Service level: [service_level_error_message]"
  8. عرض ملخص لسلسلة الأخطاء:
    • "Error Chain Summary:"
    • "File: [filename]"
    • "Operation: [operation]"
    • "Component: [component]"
    • "Service: [service_name]"
    • "Root cause: [original_error_message]"

استخدم حزمة strings لتقسيم سلاسل المدخلات عند الفواصل، وحزمة errors لإنشاء الخطأ الأصلي، وحزمة fmt لإنشاء الأخطاء المغلفة. يوضح هذا التحدي كيف ينشئ تغليف الأخطاء باستخدام %w مساراً واضحاً للسياق أثناء انتقال الأخطاء عبر طبقات مختلفة من تطبيقك، مما يجعل تصحيح الأخطاء أكثر فعالية بكثير.

ورقة مرجعية

يتيح لك تغليف الأخطاء (Error wrapping) إضافة معلومات سياقية إلى خطأ موجود مع الحفاظ على الخطأ الأصلي. استخدم فعل التنسيق %w مع fmt.Errorf:

originalErr := errors.New("file not found")
wrappedErr := fmt.Errorf("failed to load config: %w", originalErr)

يحافظ الفعل %w على الخطأ الأصلي بحيث يمكن فحصه لاحقاً باستخدام دوال مثل errors.Is و errors.As. يؤدي هذا إلى إنشاء سلسلة أخطاء تحافظ على السجل الكامل لما حدث بشكل خاطئ، وهو أمر قيم عندما تمر الأخطاء عبر دوال متعددة في التطبيقات الكبيرة.

جرّب بنفسك

package main

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

func main() {
	// قراءة المدخلات
	var fileDetails string
	var systemContext string
	fmt.Scanln(&fileDetails)
	fmt.Scanln(&systemContext)
	
	// تحليل المدخلات
	fileInfo := strings.Split(fileDetails, ",")
	filename := fileInfo[0]
	operation := fileInfo[1]
	status := fileInfo[2]
	
	contextInfo := strings.Split(systemContext, ",")
	serviceName := contextInfo[0]
	component := contextInfo[1]
	
	// TODO: اكتب الكود الخاص بك أدناه
	// إنشاء الخطأ الأصلي بناءً على الحالة
	// إنشاء خطأ مغلف على مستوى الملف
	// إنشاء خطأ مغلف على مستوى المكون
	// إنشاء خطأ مغلف على مستوى الخدمة
	// طباعة كل مستوى من مستويات الخطأ والملخص
	
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Logic & Flow