Menu

Switch case ב-Golang: fallthrough וכמה ערכים במקרה אחד

איך switch עובדת ב-Go: מקרים לא נופלים הלאה כברירת מחדל, מקרה אחד יכול לפרט כמה ערכים, switch בלי תנאי מחליפה שרשראות if/else, switch עם פקודת אתחול, מילת המפתח fallthrough, ומבט קצר על type switches.

בדף הזה יש עורכים שאפשר להריץ - לערוך, להריץ ולראות את הפלט מיד.

switch משווה ערך אחד לרשימה של מקרים ומריצה את ההתאמה הראשונה. בניגוד ל-C, ל-Java ול-JavaScript, מקרה ב-Go לא נופל הלאה למקרה הבא, כך שאין break לשכוח.

המקרים נבדקים מלמעלה למטה, ורק המקרה המתאים הראשון רץ. default רץ כששום דבר לא מתאים; הוא אופציונלי ויכול להופיע בכל מקום ברשימה, אבל לפי המוסכמה הוא בא אחרון.

כמה ערכים לכל מקרה

case "sat", "sun": מתאים לכל אחד מהערכים. כך Go מבטאת את מה ש-C עושה עם מקרים ריקים מוערמים. כל טיפוס comparable עובד: מחרוזות, מספרים, runes, בוליאנים, מצביעים וטיפוסים עם שם כמו enums:

שני מקרים עם אותו ערך קבוע הם שגיאת הידור:

./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 היה false, כך שכל מקרה יכול להניח שהמקרים שלפניו נכשלו.

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. כמה ערכים לכל מקרה מכסים את הצורך הנפוץ, וקריאות מפורשות לפונקציות בדרך כלל ברורות יותר משרשרת של fallthroughs.

break בתוך switch

break בתוך מקרה יוצא מה-switch. מקרים נגמרים מעצמם, כך שצריך אותו רק כדי לצאת ממקרה מוקדם. המלכודת היא switch בתוך לולאה:

בלי התווית loop, break מסיים את ה-switch והלולאה ממשיכה ל-"c". continue, לעומת זאת, תמיד מתייחס ללולאה העוטפת, כי switch היא לא לולאה.

Switch לפי טיפוסים

type switch מתפצל לפי הטיפוס הדינמי של ערך interface, בעזרת הצורה המיוחדת v.(type):

במקרה עם טיפוס יחיד, ל-x יש את הטיפוס הזה (len(x) עובד במקרה של string). במקרה שמפרט כמה טיפוסים, x שומר על טיפוס ה-interface. הדף על type assertions מכסה type switches ואת ה-assertion v.(T) לעומק.

מה ש-switch של Go עושה אחרת

התנהגותC, Java, JavaScriptGo
נפילה למקרה הבאברירת מחדלרק עם fallthrough
break בסוף כל מקרהחובהלא נחוץ
כמה ערכים לכל מקרהמקרים ריקים מוערמיםcase a, b, c:
ערכי מקרהקבועים (בעיקר)כל ביטוי, מוערך מלמעלה למטה
ערך ה-switchטיפוסי מספרים שלמים (C)כל טיפוס comparable
בלי ביטוי switchלא מותרswitch { case cond: }

ביטויי מקרה לא חייבים להיות קבועים. case limit(), max + 1: חוקי; הם מוערכים לפי הסדר עד שאחד מתאים, כך שביטויים מאוחרים יותר עשויים לא לרוץ אף פעם.

כיסוי מלא

Go לא בודקת ש-switch על enum מכסה כל ערך. הוסיפו default שרושם ללוג, מחזיר שגיאה או גורם ל-panic בערכים שלא ציפיתם להם, או השתמשו ב-linter בשם exhaustive (חלק מ-golangci-lint) כדי שמקרים חסרים ידווחו בזמן ה-build.

שאלות נפוצות

האם 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.

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל