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

Panic و Defer و Recover

جزء من قسم البرمجة كائنية التوجه في رحلة GO على Coddy. الدرس 57 من 107.

بينما تؤكد Go على إرجاع الأخطاء، فإن بعض الحالات لا يمكن التعافي منها حقًا. لهذه الحالات، توفر Go كلًا من panic وdefer وrecover: وهي آلية للتعامل مع الظروف الاستثنائية.

يوقف panic التنفيذ العادي فورًا. وهو مخصّص لأخطاء البرمجة مثل الوصول إلى فهرس خارج الحدود، وليس للأخطاء المتوقعة مثل إدخال مستخدم غير صالح:

func MustGetConfig(key string) string {
    value, exists := config[key]
    if !exists {
        panic("missing required config: " + key)
    }
    return value
}

تُجدوِل defer تنفيذ دالة عند عودة الدالة المحيطة، سواءً عادت بشكل طبيعي أو بسبب حالة panic. تُنفَّذ الاستدعاءات المؤجَّلة بترتيب عكسي (الأخير دخولًا، الأول خروجًا):

func ProcessFile() {
    fmt.Println("Opening file")
    defer fmt.Println("Closing file")
    fmt.Println("Processing...")
    // المخرجات: Opening file, Processing..., Closing file
}

recover يلتقط حالة panic ويعيد التنفيذ العادي. ولا يعمل إلا داخل دالة deferred:

func SafeOperation() (err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("recovered from panic: %v", r)
        }
    }()
    
    riskyOperation()
    return nil
}

يحوّل هذا النمط حالة panic إلى error عادية، مما يسمح لبرنامجك بالمتابعة. استخدمه باعتدال: يُفضَّل إرجاع error في حالات الفشل المتوقعة، واحتفظ بـ panic/recover للمواقف الاستثنائية حقًا، مثل تلف الحالة أو الظروف التي يتعذر التعافي منها.

challenge icon

التحدي

سهل

لنبنِ حاسبة قسمة آمنة توضّح كيفية استخدام panic وdefer وrecover للتعامل مع الحالات الاستثنائية بسلاسة. ستحاول الحاسبة تنفيذ عمليات محفوفة بالمخاطر وتحويل حالات panic إلى أخطاء عادية يمكن التعامل معها بشكل طبيعي.

ستنظّم الشيفرة عبر ملفين:

  • calculator.go: أنشئ منطق القسمة مع استرداد حالات panic.

    نفّذ دالة Divide تأخذ عددين صحيحين وتُحدِث حالة panic بالرسالة "division by zero" إذا كان المقسوم عليه يساوي صفراً. وإلا، فإنها تُرجع النتيجة الصحيحة للقسمة.

    نفّذ دالة SafeDivide تأخذ عددين صحيحين وتُرجع كلاً من نتيجة صحيحة وخطأ. يجب أن تقوم هذه الدالة بما يلي:

    • استخدام defer مع دالة anonymous لاسترداد أي حالة panic
    • إذا تم استرداد حالة panic، فحوّلها إلى خطأ بالتنسيق "calculation error: [panic message]"
    • استدعاء الدالة Divide داخلياً
    • إرجاع النتيجة وnil عند النجاح، أو صفراً والخطأ إذا تم استرداد حالة panic
  • main.go: اقرأ عددين صحيحين من الإدخال واستخدم SafeDivide لتنفيذ الحساب بأمان. اعرض أيضاً كيفية استخدام defer من خلال طباعة رسائل التنظيف بالترتيب الصحيح.

    يجب أن تقوم دالتك الرئيسية بما يلي:

    • طباعة Starting calculation في البداية
    • استخدام defer لجدولة طباعة Cleanup complete
    • استخدام defer آخر لجدولة طباعة Releasing resources
    • استدعاء SafeDivide باستخدام قيم الإدخال
    • طباعة Result: [value] أو Error: [error message] استناداً إلى النتيجة

سيتم توفير المدخلات التالية:

  • السطر 1: العدد الصحيح الأول (المقسوم)
  • السطر 2: العدد الصحيح الثاني (المقسوم عليه)

تذكّر أن الاستدعاءات المؤجلة تُنفَّذ بترتيب عكسي (الأخير دخولاً، الأول خروجاً)، لذا يجب أن تظهر رسائل التنظيف بترتيب معاكس للترتيب الذي تمت جدولة الاستدعاءات به.

على سبيل المثال، عند إعطاء 20 و4، يجب أن يكون الناتج:

Starting calculation
Result: 5
Releasing resources
Cleanup complete

وعند إعطاء 10 و0، يجب أن يكون الناتج:

Starting calculation
Error: calculation error: division by zero
Releasing resources
Cleanup complete
REQUIRED OUTPUT FORMAT: [Your translated content here]

جرّب بنفسك

package main

import (
	"fmt"
)

func main() {
	// اقرأ المدخلات
	var dividend, divisor int
	fmt.Scanln(&dividend)
	fmt.Scanln(&divisor)

	// اطبع رسالة البدء
	fmt.Println("Starting calculation")

	// TODO: Use defer to schedule "Cleanup complete" message

	// TODO: Use defer to schedule "Releasing resources" message
	// تذكر: استدعاءات defer تُنفَّذ بترتيب LIFO (الأخير دخولاً، الأول خروجاً)

	// TODO: استدعِ SafeDivide مع قيم الإدخال

	// TODO: اطبع إما "Result: [value]" أو "Error: [error message]"
	// بناءً على ما إذا كان قد أُرجع خطأ
}
quiz iconاختبر نفسك

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

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم Go عبر الإنترنت