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

استخدام `recover`

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

بينما يوقف panic برنامجك فوراً، توفر Go طريقة لاستعادة السيطرة من خلال الدالة recover. تسمح الدالة recover لك بالتقاط panic والتعامل معه بسلاسة، مما يمنع برنامجك بالكامل من الانهيار.

ومع ذلك، فإن recover لديه متطلب محدد للغاية: لا يمكن استخدامه إلا داخل دالة مؤجلة (deferred function). فعند حدوث panic، تقوم Go بتنفيذ جميع الدوال المؤجلة قبل انتهاء البرنامج، مما يمنح recover فرصة لاعتراض الـ panic:

func riskyFunction() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from panic:", r)
        }
    }()
    
    panic("something went wrong!")
}

تعيد الدالة recover القيمة التي تم تمريرها إلى panic، أو nil إذا لم يحدث panic. يتيح لك ذلك التحقق مما إذا كان قد حدث panic واتخاذ الإجراء المناسب، مثل تسجيل الخطأ أو إجراء عمليات التنظيف.

مثل panic، يجب استخدام recover بحذر في Go. يُشاهد هذا بشكل شائع في سيناريوهات مثل خوادم الويب حيث تريد منع حدوث panic في طلب واحد من التسبب في تعطل الخادم بالكامل، مما يسمح له بالاستمرار في خدمة الطلبات الأخرى.

quiz iconاختبر نفسك

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

quiz iconاختبر نفسك

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

quiz iconاختبر نفسك

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

challenge icon

التحدي

سهل

قم ببناء معالج طلبات لخادم ويب يستخدم recover للتعامل بلباقة مع حالات الـ panic ومنع الخادم بأكمله من الانهيار. يوضح هذا التحدي كيفية استخدام recover داخل دالة مؤجلة (deferred function) لالتقاط حالات الـ panic والحفاظ على استقرار الخادم.

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

  • سلسلة نصية تحتوي على تفاصيل الطلب بتنسيق "endpoint,method,action" (على سبيل المثال، "/api/users,GET,process")
  • سلسلة نصية تحتوي على إعدادات الخادم بتنسيق "server_name,max_requests" (على سبيل المثال، "WebServer,100")

مهمتك هي:

  1. تحليل المدخل الأول عن طريق تقسيمه بناءً على الفواصل للحصول على endpoint و method و action
  2. تحليل المدخل الثاني عن طريق تقسيمه بناءً على الفواصل للحصول على server name و max requests
  3. تحويل سلسلة max requests النصية إلى عدد صحيح (integer)
  4. إنشاء دالة تسمى handleRequest تأخذ endpoint و method و action و server name كمعاملات
  5. داخل handleRequest، أضف دالة مؤجلة (deferred function) تستخدم recover لالتقاط أي panic:
    • إذا تم استرداد panic (عندما تعيد recover قيمة غير فارغة)، اطبع: "Server [server_name] recovered from panic: [panic_value]"
    • بعد التعامل مع الـ panic، اطبع: "Request handling completed safely"
  6. بعد الدالة المؤجلة، قم بمحاكاة معالجة الطلب بناءً على الـ action:
    • إذا كان action هو "process": اطبع "Processing [method] request to [endpoint]"
    • إذا كان action هو "panic_nil": اطبع "Attempting dangerous operation" ثم استدعِ panic("nil pointer access")
    • إذا كان action هو "panic_overflow": اطبع "Attempting resource allocation" ثم استدعِ panic("memory overflow")
    • إذا كان action هو "panic_timeout": اطبع "Attempting database connection" ثم استدعِ panic("connection timeout")
    • لأي action آخر: اطبع "Unknown action: [action]" ثم استدعِ panic("invalid action")
  7. في الدالة الرئيسية (main function)، اطبع رسالة بدء تشغيل الخادم: "Starting [server_name] with max [max_requests] requests"
  8. استدعِ دالة handleRequest مع المعاملات التي تم تحليلها
  9. بعد استدعاء الدالة، اطبع حالة الخادم: "Server [server_name] is still running"
  10. أخيرًا، اطبع ملخصًا:
    • "Server Summary:"
    • "Name: [server_name]"
    • "Max Requests: [max_requests]"
    • "Last Request: [method] [endpoint]"
    • "Action Performed: [action]"
    • "Status: Operational"

استخدم حزمة strings لتقسيم سلاسل المدخلات بناءً على الفواصل وحزمة strconv لتحويل سلسلة max requests النصية إلى عدد صحيح. يوضح هذا التحدي كيف تسمح recover للخوادم بالتعامل مع حالات الـ panic غير المتوقعة بلباقة، مما يمنع فشل الطلبات الفردية من إسقاط النظام بأكمله.

ورقة مرجعية

تتيح لك الدالة recover التقاط الـ panic ومعالجته بلباقة، مما يمنع برنامجك من الانهيار.

لا يمكن استخدام recover إلا داخل دالة مؤجلة (deferred function):

func riskyFunction() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from panic:", r)
        }
    }()
    
    panic("something went wrong!")
}

تعيد الدالة recover القيمة التي تم تمريرها إلى panic، أو nil في حال لم يحدث panic. يتيح لك ذلك التحقق مما إذا كان قد حدث panic واتخاذ الإجراء المناسب.

تُستخدم recover بشكل شائع في خوادم الويب لمنع الـ panic الخاص بطلب واحد من التسبب في انهيار الخادم بأكمله.

جرّب بنفسك

package main

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

func main() {
	// قراءة المدخلات
	var requestDetails string
	var serverConfig string
	fmt.Scanln(&requestDetails)
	fmt.Scanln(&serverConfig)
	
	// تحليل تفاصيل الطلب
	requestParts := strings.Split(requestDetails, ",")
	endpoint := requestParts[0]
	method := requestParts[1]
	action := requestParts[2]
	
	// تحليل إعدادات الخادم
	configParts := strings.Split(serverConfig, ",")
	serverName := configParts[0]
	maxRequests, _ := strconv.Atoi(configParts[1])
	
	// TODO: اكتب الكود الخاص بك أدناه
	// إنشاء دالة handleRequest مع آلية الاسترداد (recover)
	// طباعة رسالة بدء تشغيل الخادم
	// استدعاء دالة handleRequest
	// طباعة حالة الخادم والملخص
	
}
quiz iconاختبر نفسك

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

جميع دروس Logic & Flow