أنماط التصميم المتقدمة في Go مع أمثلة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

أنماط التصميم في Go: المستوى المتقدم للمطورين المحترفين

\n\n

Go (Golang) هي لغة صُممت للعمل بكفاءة مع التوازي والهندسة المعمارية القائمة على الخدمات المصغرة. أنماط التصميم الأساسية مثل Singleton أو Factory معروفة جيدًا، ولكن لبناء أنظمة عالية التحميل ومقاومة للأعطال، يتطلب الأمر مستوى متقدمًا من إتقان الأنماط. في هذه المقالة، سنشرح أربعة أنماط رئيسية: Fan-Out/Fan-In وPipeline وWorker Pool وCircuit Breaker. كل منها يحل مشكلات عملية في التوسع والمعالجة المتوازية وحماية النظام من الأعطال المتتالية.

\n\n

1. نمط Fan-Out / Fan-In: معالجة البيانات المتوازية

\n\n

هذا النمط هو أساس الحوسبة المتوازية في Go. Fan-Out (المخرج المروحي) يوزع الحمل بين عدة goroutines، بينما Fan-In (المدخل المروحي) يجمع النتائج مرة أخرى في قناة واحدة.

\n\n

تنفيذ Fan-Out

\n

لنتخيل مهمة: معالجة 100 عنوان URL. بدلاً من المعالجة التسلسلية، نقوم بتشغيل 10 goroutines، كل منها تأخذ مهمة من قناة مشتركة.

\n\n
package main\n\nimport (\n    "fmt"\n    "sync"\n)\n\nfunc worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {\n    defer wg.Done()\n    for job := range jobs {\n        // محاكاة المعالجة\n        results <- job * 2\n        fmt.Printf("العامل %d قام بمعالجة المهمة %d\\n", id, job)\n    }\n}\n\nfunc main() {\n    const numJobs = 20\n    const numWorkers = 5\n\n    jobs := make(chan int, numJobs)\n    results := make(chan int, numJobs)\n    var wg sync.WaitGroup\n\n    // Fan-Out: تشغيل العمال\n    for w := 1; w <= numWorkers; w++ {\n        wg.Add(1)\n        go worker(w, jobs, results, &wg)\n    }\n\n    // إرسال المهام\n    for j := 1; j <= numJobs; j++ {\n        jobs <- j\n    }\n    close(jobs)\n\n    // Fan-In: انتظار الانتهاء وإغلاق results\n    go func() {\n        wg.Wait()\n        close(results)\n    }()\n\n    // جمع النتائج\n    for result := range results {\n        fmt.Println("النتيجة:", result)\n    }\n}\n
\n\n

النقاط الرئيسية:

\n
    \n
  • القناة jobs تعمل كنقطة Fan-Out: جميع العمال يقرؤون منها.
  • \n
  • القناة results هي نقطة Fan-In: جميع العمال يكتبون فيها.
  • \n
  • استخدام sync.WaitGroup يضمن إغلاق results فقط بعد انتهاء جميع goroutines.
  • \n
\n\n

2. نمط Pipeline: معالجة البيانات على خط التجميع

\n\n

Pipeline هو سلسلة من المراحل، حيث تقوم كل مرحلة بمعالجة البيانات وتمريرها إلى المرحلة التالية. في Go، يتم تنفيذ ذلك عبر تسلسل من القنوات. هذا النمط مثالي لعمليات ETL ومعالجة السجلات أو تحويل البيانات.

\n\n

مثال: خط تجميع معالجة النصوص

\n\n
package main\n\nimport "fmt"\n\n// المرحلة 1: توليد الأرقام\nfunc generate(nums ...int) <-chan int {\n    out := make(chan int)\n    go func() {\n        for _, n := range nums {\n            out <- n\n        }\n        close(out)\n    }()\n    return out\n}\n\n// المرحلة 2: التربيع\nfunc square(in <-chan int) <-chan int {\n    out := make(chan int)\n    go func() {\n        for n := range in {\n            out <- n * n\n        }\n        close(out)\n    }()\n    return out\n}\n\n// المرحلة 3: الضرب في 2\nfunc multiply(in <-chan int, factor int) <-chan int {\n    out := make(chan int)\n    go func() {\n        for n := range in {\n            out <- n * factor\n        }\n        close(out)\n    }()\n    return out\n}\n\nfunc main() {\n    // بناء خط التجميع\n    pipeline := multiply(square(generate(1, 2, 3, 4)), 10)\n\n    // استهلاك النتائج\n    for result := range pipeline {\n        fmt.Println(result) // 10, 40, 90, 160\n    }\n}\n
\n\n

المزايا:

\n
    \n
  • كل مرحلة مستقلة

المدونات

توصيات الكتب