الغوروتينات
Goroutines
مفهوم
~18 دقيقة
الغوروتينات — Goroutines
تخيّل أنك في مطعم. في النموذج التقليدي، هناك نادل واحد يخدم طاولة واحدة في كل مرة — إذا طاولة طلبت شيئاً يأخذ وقتاً، كل الطاولات الأخرى تنتظر. في نموذج Go، هناك عشرات النوادل الخفيفين يخدمون كل الطاولات بالتوازي — وكل نادل لا يكلّف شيئاً تقريباً.
هذا هو مفهوم goroutine: خيط تنفيذ خفيف الوزن يعمل بالتزامن مع باقي البرنامج.
ما هي الـ goroutine؟
- هي دالة تعمل بشكل متزامن مع دوال أخرى
- أخف بكثير من خيوط نظام التشغيل (thread) — حوالي 2KB من الذاكرة مقابل ~1MB للخيط
- يمكنك تشغيل آلاف أو ملايين منها بدون مشاكل
- Go runtime يدير جدولتها (scheduling) تلقائياً
كلمة go
لتشغيل goroutine، أضف كلمة go قبل استدعاء الدالة:
main.go
Output:
لاحظ كيف أن الرسائل تتداخل — هذا لأنها تعمل بالتزامن! ترتيب الرسائل قد يتغير في كل تشغيل.
goroutine مع دالة مجهولة
main.go
Output:
⚠️ الخطأ الكلاسيكي: متغير الحلقة
هذا من أشهر الأخطاء في Go (تم إصلاحه في Go 1.22 لكن يجب فهمه):
main.go
Output:
دورة حياة goroutine
goroutine تنتهي عندما:
- الدالة التي تعمل فيها تنتهي (return)
- الدالة الرئيسية
mainتنتهي — عندها كل goroutines تتوقف فوراً!
هذا يعني أنك تحتاج طريقة لانتظار goroutines — وهنا تأتي القنوات (الدرس القادم) و sync.WaitGroup.
مثال عملي: تنزيل متوازي
main.go
Output:
كم goroutine يمكنك تشغيلها؟
main.go
Output:
عشرة آلاف goroutine! جرّب ذلك مع threads في Java أو Python — ستواجه مشاكل. في Go، هذا عادي تماماً.
ملخص مهم
| المفهوم | التفاصيل |
|---|---|
go f() | يبدأ goroutine جديد |
| الحجم | ~2KB (مقابل ~1MB للـ thread) |
| العدد | يمكن تشغيل الملايين |
| الجدولة | Go runtime يديرها تلقائياً |
| الإيقاف | تنتهي مع الدالة أو مع main |
| التحذير | time.Sleep ليس حلاً حقيقياً — استخدم القنوات أو WaitGroup |
تحدي — Challenge
شغّل 3 goroutines باستخدام كلمة go واستخدم time.Sleep للانتظار