Menu
Coddy logo textTech

סיכום – מנתח קבצים

חלק מהיחידה תכנות מונחה עצמים במסלול ה-GO של Coddy. שיעור 58 מתוך 107.

challenge icon

אתגר

קל

בואו נבנה מנתח לקובצי תצורה שמשלב את כל טכניקות הטיפול בשגיאות מהפרק הזה. המנתח שלכם יטפל בכמה תרחישי כשל באמצעות סוגי שגיאות מותאמים אישית, שגיאות סמן, עטיפת שגיאות וניקוי תקין באמצעות defer.

ארגנו את הקוד שלכם בשלושה קבצים:

  • errors.go: הגדירו את תשתית השגיאות של המנתח.

    צרו שתי שגיאות סמן:

    • ErrEmptyContent עם ההודעה "file content is empty"
    • ErrInvalidFormat עם ההודעה "invalid configuration format"

    צרו סוג שגיאה מותאם אישית ParseError עם השדות Line (int) ו-Message (string). המתודה Error() שלו צריכה להחזיר: parse error at line [Line]: [Message]

  • parser.go: בנו את מנתח התצורה עם טיפול בשגיאות בכמה שכבות.

    צרו מבנה ConfigParser עם שדה בוליאני parsed כדי לעקוב אחר השלמת הניתוח בהצלחה.

    ממשו את המתודות הבאות:

    • NewConfigParser() *ConfigParser - יוצרת מנתח חדש כאשר parsed מוגדר ל-false
    • ParseLine(lineNum int, line string) error - מאמתת שורה בודדת. אם השורה אינה מכילה את התו =, החזירו *ParseError עם מספר השורה וההודעה "missing key-value separator". אחרת, החזירו nil.
    • Parse(content string) error - מתודת הניתוח הראשית ש:
      • מחזירה ErrEmptyContent אם התוכן ריק
      • מחזירה ErrInvalidFormat אם התוכן אינו מכיל לפחות תו של ירידת שורה אחד
      • מפצלת את התוכן לפי ירידות שורה וקוראת ל-ParseLine עבור כל שורה (מספור השורות מתחיל ב-1)
      • אם ParseLine מחזירה שגיאה, עטפו אותה באמצעות "parsing configuration: %w" והחזירו אותה
      • מגדירה את parsed ל-true במקרה של הצלחה ומחזירה nil
    • Status() string - מחזירה "ready" אם parsed הוא true, ואחרת "not parsed"
  • main.go: קראו את תוכן התצורה והדגימו בדיקה מקיפה של שגיאות.

    קראו שתי שורות קלט שמרכיבות יחד את תוכן התצורה (חברו אותן באמצעות ירידת שורה). השתמשו ב-defer כדי להדפיס תמיד את המצב של המנתח בסוף, בין אם הפעולה הצליחה ובין אם נכשלה.

    לאחר ניסיון הניתוח, בדקו כל שגיאה באמצעות errors.Is() וגם באמצעות errors.As(), כדי לספק משוב ספציפי בהתאם לסיבה לכשל.

הקלטים הבאים יסופקו:

  • שורה 1: השורה הראשונה של תוכן התצורה
  • שורה 2: השורה השנייה של תוכן התצורה

טפלו בשגיאות באמצעות הודעות ספציפיות:

  • אם errors.Is() מוצאת את ErrEmptyContent: הדפיסו Error: No configuration provided
  • אם errors.Is() מוצאת את ErrInvalidFormat: הדפיסו Error: Configuration must have multiple lines
  • אם errors.As() מוצאת *ParseError: הדפיסו את השגיאה המלאה והעטופה, ואז בשורה חדשה הדפיסו Fix line [Line]: [Message]
  • אם הניתוח מצליח: הדפיסו Configuration parsed successfully

לאחר הטיפול בתוצאה (הצלחה או שגיאה), המצב הנדחה צריך להיות מודפס בשורה חדשה: Parser status: [status]

לדוגמה, עבור host=localhost ו-port=8080, הפלט שלכם צריך להיות:

Configuration parsed successfully
Parser status: ready

ועבור host=localhost ו-invalid line, הפלט שלכם צריך להיות:

parsing configuration: parse error at line 2: missing key-value separator
Fix line 2: missing key-value separator
Parser status: not parsed

נסו בעצמכם

package main

import (
	"bufio"
	"errors"
	"fmt"
	"os"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	
	// קרא את השורה הראשונה של התצורה
	line1, _ := reader.ReadString('\n')
	line1 = line1[:len(line1)-1] // הסר את תו ירידת השורה שבסוף
	
	// קרא את השורה השנייה של התצורה
	line2, _ := reader.ReadString('\n')
	if len(line2) > 0 && line2[len(line2)-1] == '\n' {
		line2 = line2[:len(line2)-1]
	}
	
	// חבר את שתי השורות באמצעות תו ירידת שורה כדי ליצור את תוכן התצורה
	content := line1 + "\n" + line2
	
	// צור מנתח חדש
	parser := NewConfigParser()
	
	// TODO: השתמש ב-defer כדי להדפיס תמיד את מצב המנתח בסוף
	// פורמט: "Parser status: [status]"
	
	// TODO: נסה לנתח את התוכן
	
	// TODO: טפל בשגיאות באמצעות errors.Is() ו-errors.As()
	// - אם errors.Is() מזהה את ErrEmptyContent: הדפס "Error: No configuration provided"
	// - אם errors.Is() מזהה את ErrInvalidFormat: הדפס "Error: Configuration must have multiple lines"
	// - אם errors.As() מזהה שגיאה מסוג *ParseError: הדפס את השגיאה העטופה במלואה,
	//   ואז בשורה חדשה הדפס "Fix line [Line]: [Message]"
	// - אם הפענוח מצליח: הדפס "Configuration parsed successfully"
	
	_ = errors.Is // רמז: השתמש ב-errors.Is לשגיאות sentinel
	_ = errors.As // רמז: השתמש ב-errors.As עבור סוגי שגיאות מותאמים אישית
	_ = fmt.Println
}

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר Go אונליין