Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

ملخص - File Parser

جزء من قسم Object Oriented Programming في رحلة GO على Coddy — الدرس 58 من 107.

challenge icon

التحدي

سهل

لنقم ببناء محلل لملفات التكوين (configuration file parser) يجمع بين جميع تقنيات معالجة الأخطاء الواردة في هذا الفصل. سيتعامل المحلل الخاص بك مع سيناريوهات فشل متعددة باستخدام أنواع أخطاء مخصصة، وأخطاء مرجعية (sentinel errors)، وتغليف الأخطاء (error wrapping)، والتنظيف المناسب باستخدام defer.

ستقوم بتنظيم الكود الخاص بك عبر ثلاثة ملفات:

  • errors.go: حدد البنية التحتية للأخطاء الخاصة بالمحلل.

    قم بإنشاء خطأين مرجعيين (sentinel errors):

    • 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 لتتبع ما إذا كانت عملية التحليل قد اكتملت بنجاح.

    قم بتنفيذ هذه الطرق (methods):

    • 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 صحيحة، وإلا ترجع "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

بعد معالجة النتيجة (نجاح أو خطأ)، يجب أن تطبع الحالة المؤجلة (deferred status) في سطر جديد: 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)
	_ = errors.As // تلميح: استخدم errors.As لأنواع الأخطاء المخصصة
	_ = fmt.Println
}

جميع دروس Object Oriented Programming