قوائم المهام في Go للمبتدئين: دليل شامل

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

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

ابدأ الدورة

العمل مع قوائم المهام في Go: للمبتدئين



قوائم المهام (task queues) هي أحد الأنماط الأساسية في التطوير الحديث. في Go (Golang) يتم تنفيذ هذه الآلية بشكل أنيق بفضل أدوات التوازي المدمجة: goroutines والقنوات. في هذه المقالة، سنشرح كيفية إنشاء قوائم المهام في Go، بدءًا من الأمثلة البسيطة وصولاً إلى التقنيات المتقدمة.



ما هي قائمة المهام ولماذا نحتاجها؟



قائمة المهام هي بنية بيانات تعمل وفق مبدأ FIFO (First In, First Out - "من يدخل أولاً يخرج أولاً"). تخيل طابورًا أمام شباك التذاكر: أول شخص يتم خدمته، ثم الثاني، وهكذا. في البرمجة، يتيح ذلك:



  • فصل استلام المهام عن معالجتها
  • تحديد عدد العمليات المنفذة في وقت واحد
  • توزيع الحمل بالتساوي بين المعالجات
  • معالجة المهام في الخلفية دون حظر التدفق الرئيسي


Go مثالي لتنفيذ قوائم المهام بفضل نموذج التوازي الخاص به. على عكس العديد من اللغات التي تتطلب مكتبة خارجية (مثل RabbitMQ أو Redis)، يمكنك في Go إنشاء قائمة مهام بسيطة ببضعة أسطر من الكود.



إنشاء قائمة مهام بسيطة باستخدام قنوات Go



أبسط طريقة لتنفيذ قائمة مهام هي استخدام قناة مخزنة مؤقتًا. دعنا نلقي نظرة على مثال أساسي:



package main

import ( "fmt" "time")

func worker(tasks <-chan string, id int) { for task := range tasks { fmt.Printf("العامل %d بدأ المهمة: %s", id, task) time.Sleep(1 * time.Second) // محاكاة العمل fmt.Printf("العامل %d أكمل المهمة: %s", id, task) }}

func main() { tasks := make(chan string, 5) // قناة مخزنة تتسع لـ 5 مهام

// تشغيل عاملين for i := 1; i <= 2; i++ { go worker(tasks, i) }

// إرسال المهام إلى القائمة for i := 1; i <= 10; i++ { tasks <- fmt.Sprintf("المهمة رقم %d", i) }

close(tasks) // إغلاق القناة بعد إرسال جميع المهام time.Sleep(2 * time.Second) // إعطاء وقت للانتهاء}


في هذا المثال:

  • القناة tasks تعمل كقائمة مهام
  • عاملان (goroutines) يستمعان باستمرار إلى القناة ويعالجان المهام
  • المخزن المؤقت بحجم 5 يسمح بإرسال ما يصل إلى 5 مهام دون معالجة فورية


نمط Worker Pool: معالجة قابلة للتوسع



Worker Pool (مجموعة العمال) هو تطور لقائمة المهام البسيطة. بدلاً من عدد ثابت من العمال، نقوم بإنشاء مجموعة يمكن توسيعها ديناميكيًا. هذا النمط مفيد بشكل خاص لـ:



  • معالجة طلبات HTTP
  • معالجة البيانات على دفعات
  • العمل مع واجهات برمجة التطبيقات الخارجية (تحديد عدد الطلبات المتزامنة)


إليك تنفيذ أكثر تقدمًا باستخدام هيكل:



package main

import ( "fmt" "sync" "time")

type Task struct { ID int Payload string}

type WorkerPool struct { tasks chan Task results chan string wg sync.WaitGroup workers int}

func NewWorkerPool(workers int) *WorkerPool { return &WorkerPool{ tasks: make(chan Task, 100), results: make(chan string, 100), workers: workers, }}

func (wp *WorkerPool) Start() { for i := 1; i <= wp.workers; i++ { wp.wg.Add(1) go wp.worker(i) }}

func (wp *WorkerPool) worker(id int) { defer wp.wg.Done() for task := range wp.tasks { result := fmt.Sprintf("العامل %d نفذ المهمة %d: %s", id, task.ID, task.Payload) time.Sleep(500 * time.Millisecond) // محاكاة العمل wp.results <- result }}

func (wp *WorkerPool) AddTask(task Task) { wp.tasks <- task}\

المدونات

توصيات الكتب