להחזיר יותר מערך אחד
רשמו את טיפוסי התוצאות בסוגריים. החזירו את הערכים מופרדים בפסיקים, וקבלו אותם באותה צורה.
הפונקציות המובנות min ו-max קיימות מאז Go 1.21. הקוד הקורא חייב לקבל כל תוצאה: x := minMax(nums) לא מתקמפל, עם assignment mismatch: 1 variable but minMax returns 2 values.
המוסכמה (value, error)
הסיבה הנפוצה ביותר להחזיר שני ערכים היא לדווח על כישלון. לפי המוסכמה השגיאה באה אחרונה, וכשהיא לא nil צריך להתייחס לשאר התוצאות כחסרות משמעות.
פלט:
port: 8080
error: port "http": strconv.Atoi: parsing "http": invalid syntax
error: port out of range
בכישלון, החזירו את ערך האפס לכל שאר התוצאות (0, "", nil). התבנית המלאה, כולל עטיפה ובדיקה, נמצאת בעמוד על טיפול בשגיאות.
הביטוי comma-ok
כמה פעולות מובנות מחזירות bool שני ואופציונלי שאומר אם הערך הראשון אמיתי. לפי המוסכמה, המשתנה נקרא ok.
שלוש הצורות האלה (חיפוש ב-map, type assertion, קבלה מ-channel) מיוחדות: הן מחזירות ערך אחד או שניים, לפי מספר המשתנים שאליהם משימים. הפונקציות שלכם לא יכולות לעשות את זה. פונקציה שהוצהרה עם שתי תוצאות תמיד מחזירה שתיים.
המזהה הריק
_ מקבל ערך וזורק אותו. השתמשו בו לתוצאות שאתם לא צריכים:
_, err := fmt.Sscan(input, &n)
key, _ := parseLine(line)
התעלמות משגיאה עם _ מתקמפלת, אז עשו את זה רק כשאתם יודעים שהקריאה לא יכולה להיכשל, או שהכישלון לא משנה. למשל, strings.Builder.WriteString תמיד מחזירה שגיאה שהיא nil; סגירת קובץ אחרי כתיבה לא.
Named results
לפרמטרים של תוצאה יכולים להיות שמות. הם מוצהרים בתחילת הפונקציה, מאותחלים לערכי האפס שלהם, ו-return בלי ערכים מחזיר את מה שהם מחזיקים.
השמות מופיעים בפלט של go doc, וזה עוזר כששתי תוצאות מאותו טיפוס: (quotient, remainder int) אומר יותר מ-(int, int).
return חשוף בפונקציה ארוכה קשה לקריאה, כי הקורא צריך לחזור אחורה כדי לראות מה התוצאות מחזיקות. ההמלצה המקובלת: תנו שמות לתוצאות כשהשמות מתעדים משהו, ועדיין כתבו return quotient, remainder במפורש, אלא אם הפונקציה באורך של כמה שורות.
Named results ו-defer
פונקציה שנדחתה עם defer רצה אחרי שפקודת ה-return קבעה את התוצאות ולפני שהקוד הקורא מקבל אותן. עם named results, הפונקציה שנדחתה יכולה לקרוא אותן ולשנות אותן. כך מוסיפים הקשר לכל שגיאה שפונקציה מחזירה, או הופכים panic לשגיאה.
זה מדפיס load : empty name ואחר כך <nil>. return errors.New(...) קודם משים ל-err, ואז הפונקציה שנדחתה עוטפת אותו. עוד על זה בעמוד על defer.
הצללה של named result
named results חיים ב-scope החיצוני ביותר של הפונקציה. := בתוך בלוק מקונן יוצר משתנה חדש עם אותו שם, ו-return חשוף מחזיר אז את החיצוני.
func find() (n int, err error) {
if true {
n, err := compute() // new n and err, shadowing the results
_ = n
_ = err
}
return // returns 0, nil
}
הקומפיילר תופס את המקרה הגרוע ביותר: return חשוף בתוך הבלוק שבו תוצאה מוצללת נכשל עם result parameter err not in scope at return. הוא לא תופס את הגרסה שלמעלה, שבה ה-return נמצא מחוץ לבלוק. השתמשו ב-= במקום ב-:= כשאתם מתכוונים למשתני התוצאה.
טעויות נפוצות
- שימוש בערך כש-err הוא לא nil. בדקו קודם את
err. פונקציה רשאית להחזיר זבל לצד שגיאה. - החזרת pointer מטיפוס מסוים שהוא nil בתור שגיאה.
var e *MyErr; return eמחזירerrorשהוא לא nil. החזירוnilמפורש בהצלחה. - יותר מדי תוצאות. שלוש תוצאות או יותר עם משמעויות שונות קשות לשימוש. החזירו struct במקום.
שאלות נפוצות
איך מחזירים כמה ערכים מפונקציה ב-Go?
רשמו את טיפוסי התוצאות בסוגריים והחזירו את הערכים מופרדים בפסיקים: func minMax(xs []int) (int, int) { ...; return lo, hi }. הקוד הקורא מקבל את כולם בבת אחת: lo, hi := minMax(nums).
איך מתעלמים מאחד מערכי ההחזרה ב-Go?
השימו אותו למזהה הריק _: _, err := strconv.Atoi(s) או n, _ := strconv.Atoi(s). אי אפשר פשוט להשמיט ערך: מספר המשתנים שמקבלים את הערכים חייב להתאים למספר התוצאות.
מה הם named return values ב-Go?
פרמטרים של תוצאה שיש להם שמות, כמו func split(n int) (half, rest int). הם מתחילים בערכי האפס שלהם, אפשר להשים להם ערכים בגוף הפונקציה, ו-return בלי ערכים מחזיר את הערכים הנוכחיים שלהם. הם גם מאפשרים לפונקציה שנדחתה עם defer לשנות את מה שהקוד הקורא מקבל.
כדאי להשתמש ב-return חשוף (naked return) ב-Go?
רק בפונקציות קצרות. return בלי ערכים בפונקציה ארוכה מסתיר מה מוחזר ומקל על באגים של הצללה. מדריכי הסגנון של Go ממליצים לתת שמות לתוצאות לשם תיעוד, ולהחזיר ערכים מפורשים בכל פונקציה שארוכה מכמה שורות.