تقارن switch قيمة واحدة بقائمة حالات وتنفّذ أول مطابقة. وبخلاف C وJava وJavaScript، لا تنتقل الحالة في Go إلى التالية، فلا توجد break لتنساها.
تُفحص الحالات من الأعلى إلى الأسفل، ولا تُنفَّذ إلا أول حالة مطابقة. تُنفَّذ default عندما لا يطابق شيء؛ وهي اختيارية ويمكن أن تظهر في أي مكان من القائمة، لكنها توضع أخيرًا اصطلاحًا.
عدة قيم لكل حالة
تطابق case "sat", "sun": أيًا من القيمتين. هكذا تعبّر Go عمّا تفعله C بالحالات الفارغة المكدّسة. يعمل أي نوع قابل للمقارنة: النصوص والأرقام والـ runes والقيم المنطقية والمؤشرات والأنواع المسمّاة مثل التعدادات:
حالتان بالقيمة الثابتة نفسها خطأ ترجمة:
./main.go:10:7: duplicate case 1 (constant of type int) in expression switch
./main.go:8:7: previous case
switch دون شرط
احذف التعبير فتصبح كل حالة اختبارًا منطقيًا. هذا هو الشكل الأنظف في Go لسلسلة if/else if طويلة:
switch { اختصار لـ switch true {. ولأن أول حالة صحيحة تفوز، فالترتيب مهم: لا يُوصل إلى bmi < 25 إلا عندما يكون bmi < 18.5 خاطئًا، فتستطيع كل حالة افتراض أن الحالات التي قبلها فشلت.
switch مع عبارة تهيئة
مثل if، يمكن أن تبدأ switch بعبارة قصيرة. والمتغيّرات المعرّفة فيها نطاقها هو switch:
ويمكن أيضًا دمج عبارة التهيئة مع switch دون تعبير: switch n := len(items); { case n == 0: ... }.
fallthrough
عندما تريد فعلًا الاستمرار في الحالة التالية، اكتب fallthrough كآخر عبارة في الحالة. تنقل التحكّم إلى جسم الحالة التالية دون تقييم شرطها:
يطبع المستوى 2 write ثم read، فتتراكم الصلاحيات نزولًا. لا تُفحص شروط الحالات اللاحقة: بعد fallthrough من case 2 تُنفَّذ case 1 رغم أن level يساوي 2.
قواعد fallthrough:
- يجب أن تكون آخر عبارة في الحالة.
- لا يمكن أن تظهر في الحالة الأخيرة:
cannot fallthrough final case in switch. - غير مسموحة في type switch.
عمليًا fallthrough نادرة في شيفرات Go. القيم المتعدّدة لكل حالة تغطّي الحاجة الشائعة، والاستدعاءات الصريحة للدوال أوضح عادة من سلسلة fallthrough.
break في switch
تخرج break داخل حالة من switch. الحالات تنتهي وحدها، فلا تحتاجها إلا للخروج من حالة مبكرًا. الفخ هو switch داخل حلقة:
دون الوسم loop تنهي break عبارة switch وتستمر الحلقة إلى "c". أما continue فتشير دائمًا إلى الحلقة المحيطة، لأن switch ليست حلقة.
switch على الأنواع
يتفرّع type switch حسب النوع الديناميكي لقيمة واجهة، باستخدام الصيغة الخاصة v.(type):
في حالة بنوع واحد يكون لـ x ذلك النوع (تعمل len(x) في حالة string). وفي حالة تسرد عدة أنواع يحتفظ x بنوع الواجهة. صفحة تأكيدات النوع تشرح type switch والتأكيد v.(T) بالتفصيل.
ما تفعله switch في Go بشكل مختلف
| السلوك | C وJava وJavaScript | Go |
|---|---|---|
| الانتقال إلى الحالة التالية | افتراضي | فقط مع fallthrough |
break في نهاية كل حالة | مطلوبة | غير مطلوبة |
| عدة قيم لكل حالة | حالات فارغة مكدّسة | case a, b, c: |
| قيم الحالات | ثوابت (غالبًا) | أي تعبير، يُقيَّم من الأعلى إلى الأسفل |
| قيمة switch | أنواع صحيحة (C) | أي نوع قابل للمقارنة |
| دون تعبير switch | غير مسموح | switch { case cond: } |
لا يجب أن تكون تعابير الحالات ثوابت. case limit(), max + 1: مسموحة؛ وتُقيَّم بالترتيب حتى تطابق إحداها، فقد لا تُنفَّذ التعابير اللاحقة أبدًا.
الشمول
لا تتحقّق Go من أن switch على تعداد يغطّي كل قيمة. أضف default تسجّل أو تعيد خطأ أو تسبّب panic للقيم التي لم تتوقّعها، أو استخدم أداة الفحص exhaustive (جزء من golangci-lint) ليُبلَّغ عن الحالات الناقصة وقت البناء.
الأسئلة الشائعة
هل تنتقل switch في Go إلى الحالة التالية؟
لا. تنتهي الحالة في Go عند case التالية تلقائيًا؛ ولا تكتب break أبدًا لإيقافها. إذا أردت أن يستمر التنفيذ في جسم الحالة التالية، فاكتب fallthrough كآخر عبارة في الحالة. وهي تقفز دون شرط، دون فحص شرط الحالة التالية.
كيف أطابق عدة قيم في حالة واحدة في Go؟
اسردها مفصولة بفواصل: case "sat", "sun":. تُنفَّذ الحالة إذا ساوت قيمة switch أيًا منها. وهذا يحلّ محل الحالات الفارغة المكدّسة التي تكتبها في C أو Java.
ما هي switch دون شرط في Go؟
switch { case x < 0: ...; case x == 0: ...; default: ... }. دون تعبير بعد switch تصبح كل حالة شرطًا منطقيًا وتُنفَّذ أول حالة صحيحة. وهي البديل المعتاد لسلسلة if/else if طويلة.
ماذا تفعل break داخل switch في Go؟
تنهي switch، لا حلقة for محيطة. نادرًا ما تُحتاج لأن الحالات تنتهي وحدها، لكنها تفاجئ من يكتب break داخل switch داخل حلقة متوقّعًا الخروج من الحلقة. استخدم break بوسم أو return لذلك.