لماذا سؤال "Is there a way to iterate over a range of integers?" شائع جدًا؟
\n\nإذا كنت قد أتيت إلى Go من Python، فمن المحتمل أنك تتذكر for i in range(10): الأنيق. في Python، يعمل هذا كالساعة. في Go... الأمر مختلف قليلاً. السؤال على Stack Overflow بهذا العنوان جمع آلاف المشاهدات - وهذا ليس من قبيل الصدفة. المطورون المعتادون على التجريدات عالية المستوى غالبًا ما يضيعون عندما يواجهون بناء جملة Go البسيط.
في هذه المقالة، سنستعرض جميع طرق التكرار عبر نطاق من الأعداد الصحيحة في Go: من for الكلاسيكي إلى الأدوات الحديثة. ستتعرف على الطريقة التي يجب اختيارها لتحقيق أقصى أداء، وأيها لتحقيق قابلية قراءة الكود. هيا بنا!
الطريقة رقم 1: for الكلاسيكي (Go الاصطلاحي)
\n\nGo هي لغة البراغماتيين. لا تحتوي على range مدمج للأرقام، ولكن لديها for قوي. الطريقة الأبسط والأكثر أداءً هي استخدام حلقة ثلاثية المكونات:
package main\n\nimport "fmt"\n\nfunc main() {\n // التكرار من 0 إلى 9 (إجمالي 10 عناصر)\n for i := 0; i < 10; i++ {\n fmt.Println(i)\n }\n}\n\nهذا الكود فعال للغاية: يحوله المترجم إلى زيادة بسيطة في السجل. لا توجد عمليات تخصيص ذاكرة، ولا تكاليف إضافية. هذه هي الطريقة التي يكتب بها مطورو Go في بيئة الإنتاج.
\n\nمتغيرات for الكلاسيكي
\n\nيمكنك بسهولة تغيير القيمة الأولية والخطوة:
\n\n// من 5 إلى 15\nfor i := 5; i <= 15; i++ {\n fmt.Println(i)\n}\n\n// الأرقام الزوجية فقط من 0 إلى 20\nfor i := 0; i <= 20; i += 2 {\n fmt.Println(i)\n}\n\n// ترتيب عكسي: من 10 إلى 1\nfor i := 10; i >= 1; i-- {\n fmt.Println(i)\n}\n\nهذا الأسلوب هو المعيار الذهبي للتكرار عبر نطاق من الأرقام في Go. إنه بسيط وواضح ولا يتطلب استيراد حزم إضافية.
\n\nالطريقة رقم 2: استخدام range مع شريحة (لعشاق Python)
\n\nإذا كنت تفتقد أسلوب Python بشدة، يمكنك إنشاء شريحة والتكرار عبرها باستخدام range. لكن كن حذرًا: هذا يؤثر بشدة على الأداء.
package main\n\nimport "fmt"\n\nfunc main() {\n // إنشاء شريحة من الأرقام من 0 إلى 9\n numbers := make([]int, 10)\n for i := range numbers {\n numbers[i] = i\n }\n\n // الآن نستخدم range للتكرار\n for _, num := range numbers {\n fmt.Println(num)\n }\n}\n\nلماذا هذا سيء؟ تخصيص الذاكرة. في كل مرة تقوم فيها بإنشاء شريحة، يخصص Go ذاكرة في الكومة. بالنسبة لنطاق من 10 عناصر، هذا غير ملحوظ، ولكن بالنسبة لـ 10 ملايين، فهذه مشكلة.
\n\nاختبار الأداء: for مقابل range مع شريحة
\n\nدعنا نلقي نظرة على الأرقام (التكرار عبر 1,000,000 رقم):
\n\n- \n
- for الكلاسيكي: ~2.5 مللي ثانية، 0 تخصيصات \n
- Range مع شريحة: ~45 مللي ثانية، تخصيص واحد (8 ميجابايت) \n
الفرق 18 مرة! وهذا فقط لمليون عنصر. بالنسبة للنطاقات الأكبر، الفجوة تزداد فقط.
\n\nالطريقة رقم 3: استخدام المكتبات (iter, lo, وغيرها)
\n\nمجتمع Go لا يقف مكتوف الأيدي. توجد مكتبات خارجية تضيف سكرًا نحويًا للتكرار عبر النطاق. دعنا نستعرض اثنتين شائعتين:
\n\n3.1 حزمة iter (تجريبية، Go 1.23+)
\n\nبدءًا من Go 1.23، ظهرت حزمة تجريبية iter في المكتبة القياسية، والتي تسمح بإنشاء مكررات. إنها غير مستقرة بعد، ولكنها متاحة بالفعل:
package main\n\nimport (\n "fmt"\n "iter"\n)\n\nfunc main() {\n // إنشاء مكرر من 0 إلى 9\n seq := iter.Seq[int](func(yield func(int) bool) {\n for i := 0; i < 10; i++ {\n if !yield(i) {\n return\n }\n }\n })\n\n for num := range seq {\n fmt.Println(num)\n }\n}