חילוץ שגיאות באמצעות `errors.As`
חלק מהיחידה לוגיקה וזרימת התוכנית במסלול ה-GO של Coddy. שיעור 41 מתוך 68.
בעוד ש-errors.Is עוזרת לך לזהות ערכי שגיאה ספציפיים בשרשרת, לפעמים צריך לגשת לשדות ולנתונים בפועל של סוג שגיאה מותאם אישית. הפונקציה errors.As מאפשרת זאת על ידי מציאת השגיאה הראשונה בשרשרת שתואמת לסוג מסוים וחילוצה לבדיקה.
הפונקציה errors.As מקבלת שני פרמטרים: השגיאה שיש לבדוק ומצביע למשתנה מסוג שגיאת היעד. אם היא מוצאת סוג שגיאה תואם בשרשרת, היא מציבה את השגיאה במשתנה שלך ומחזירה true:
var validationErr ValidationError
if errors.As(wrappedErr, &validationErr) {
fmt.Printf("Field: %s, Message: %s\n", validationErr.Field, validationErr.Message)
}הדבר עוצמתי במיוחד כשעובדים עם סוגי שגיאות מותאמים אישית שמכילים הקשר נוסף. בניגוד ל־errors.Is, שבודקת שוויון בלבד, errors.As מחלצת את מופע השגיאה עצמו, וכך מאפשרת לך לגשת לשדות ולמתודות שלו. הדבר הופך את הטיפול בשגיאות למתוחכם ואינפורמטיבי יותר ביישומים מורכבים.
אתגר
קלבנו מערכת לטיפול בשגיאות API שמשתמשת ב-errors.As כדי לחלץ ולבחון סוגי שגיאות מותאמים אישית מתוך שרשראות של שגיאות עטופות. האתגר הזה מדגים כיצד להשתמש ב-errors.As כדי לגשת לשדות ולנתונים של סוגי שגיאות מותאמים אישית מסוימים, גם כשהם נעטפו בהקשר נוסף.
תקבלו שתי קלטות:
- מחרוזת המכילה פרטים על בקשת API בפורמט
"endpoint,method,error_code,error_field"(לדוגמה,"/users,POST,400,email") - מחרוזת המכילה הקשר מערכת בפורמט
"service_name,request_id"(לדוגמה,"UserAPI,req_12345")
המשימה שלכם:
- צרו סוג שגיאה מותאם אישית בשם מבנה
APIErrorעם שלושה שדות:Code(int) - קוד מצב HTTPField(string) - השדה שגרם לשגיאהMessage(string) - תיאור של השגיאה
- ממשו את המתודה
Error() stringעבורAPIError, כך שתחזיר:"API error [code]: [message] (field: [field])" - נתחו את הקלט הראשון באמצעות פיצול לפי פסיקים כדי לקבל את נקודת הקצה, השיטה, קוד השגיאה ושדה השגיאה
- נתחו את הקלט השני באמצעות פיצול לפי פסיקים כדי לקבל את שם השירות ומזהה הבקשה
- המירו את מחרוזת קוד השגיאה למספר שלם
- צרו מופע של
APIErrorעל סמך קוד השגיאה:- אם הקוד הוא 400: ההודעה
"invalid request data" - אם הקוד הוא 401: ההודעה
"authentication required" - אם הקוד הוא 404: ההודעה
"resource not found" - אם הקוד הוא 500: ההודעה
"internal server error" - עבור כל קוד אחר: ההודעה
"unknown error"
- אם הקוד הוא 400: ההודעה
- צרו שגיאה עטופה ברמת נקודת הקצה באמצעות
fmt.Errorfעם%w:"[method] [endpoint] failed: %w" - צרו שגיאה עטופה ברמת השירות:
"[service_name] request [request_id] failed: %w" - השתמשו ב-
errors.Asכדי לחלץ אתAPIErrorמשרשרת השגיאות העטופות ולהציג את תוצאת החילוץ:- אם החילוץ מצליח:
"API error extracted successfully" - אם החילוץ נכשל:
"Failed to extract API error"
- אם החילוץ מצליח:
- אם החילוץ הצליח, הציגו את פרטי השגיאה שחולצה:
"Extracted Error Details:""Code: [code]""Field: [field]""Message: [message]""Full error: [full_error_message_from_Error_method]"
- הציגו את שרשרת השגיאות המלאה:
"Error Chain:""Original: [original_api_error_message]""Endpoint level: [endpoint_level_error_message]""Service level: [service_level_error_message]"
- הציגו ניתוח סופי:
"Error Analysis:""Service: [service_name]""Request ID: [request_id]""Endpoint: [method] [endpoint]""HTTP Status: [code]""Problem Field: [field]""Error Category: [error_category]"כאשר error_category הוא "Client Error" עבור קודים 400-499, "Server Error" עבור קודים 500-599, או "Unknown" עבור קודים אחרים
השתמשו בחבילת strings כדי לפצל את מחרוזות הקלט לפי פסיקים, בחבילת strconv כדי להמיר את מחרוזת קוד השגיאה למספר שלם, בחבילת errors עבור errors.As, ובחבילת fmt לעטיפת שגיאות. האתגר הזה מדגים כיצד errors.As מאפשרת לכם לגשת לשדות ולמתודות מסוימים של סוגי שגיאות מותאמים אישית בתוך שרשראות של שגיאות עטופות, וכך לאפשר טיפול וניתוח מתוחכמים של שגיאות.
נסו בעצמכם
package main
import (
"errors"
"fmt"
"strconv"
"strings"
)
func main() {
// קרא את הקלט
var apiDetails string
var systemContext string
fmt.Scanln(&apiDetails)
fmt.Scanln(&systemContext)
// נתח את נתוני הקלט
apiParts := strings.Split(apiDetails, ",")
endpoint := apiParts[0]
method := apiParts[1]
errorCodeStr := apiParts[2]
errorField := apiParts[3]
contextParts := strings.Split(systemContext, ",")
serviceName := contextParts[0]
requestID := contextParts[1]
// המר את קוד השגיאה למספר שלם
errorCode, _ := strconv.Atoi(errorCodeStr)
// TODO: כתוב את הקוד שלך למטה
// 1. צור struct מסוג APIError עם השדות Code, Field, Message
// 2. ממש את המתודה Error() עבור APIError
// 3. צור מופע של APIError על סמך קוד השגיאה
// 4. צור שגיאות עטופות (ברמת ה-endpoint וברמת השירות)
// 5. השתמש ב-errors.As כדי לחלץ APIError משרשרת השגיאות העטופות
// 6. הצג את תוצאת החילוץ ואת פרטי השגיאה
// 7. הצג את שרשרת השגיאות ואת הניתוח הסופי
}השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה לוגיקה וזרימת התוכנית
1בקרת זרימה מתקדמת
switch עם `fallthrough`יציאה מלולאות מקוננותהמשך לולאה מסוימתהצהרת `goto`סיכום – שליטה מתקדמת בלולאות4פרויקט: רשימת משימות פשוטה
הגדרת הפרויקטהוספת משימה7טיפול בשגיאות לעומק
סוגי שגיאות מותאמים אישיתעטיפת שגיאות באמצעות `%w`חילוץ שגיאות באמצעות `errors.Is`חילוץ שגיאות באמצעות `errors.As`הבנת `panic`שימוש ב־`recover`סיכום — חלוקה בטוחה2מבנים ושיטות
הגדרת שיטות במבניםמקבלי ערךמקבלי מצביעבחירת מקבליםשיטות לעומת פונקציותסיכום — התנהגות המבנים5מפות לעומק
מפות של Structsמצביעים כערכים במפהבדיקה אם מפות הן nilהשוואת מפותסיכום - מונה תדירות מילים8פרויקט: ניהול מלאי פשוט
סקירת הפרויקטבדיקת המלאיתרגלו בעצמכם: קומפיילר Go אונליין