العمل مع نظام الملفات في Go: عمليًا
\n\nالعمل مع نظام الملفات هو أحد المهام الأساسية لأي تطبيق خادم. توفر لغة Go (Golang) مجموعة أدوات قوية وأنيقة لقراءة وكتابة وحذف وإدارة الملفات والمجلدات. في هذه المقالة، سنستعرض أمثلة عملية للعمل مع الملفات في Go باستخدام الحزم القياسية os و io/ioutil (قبل Go 1.16) و io. ستتعلم كيفية إدارة البيانات على القرص بكفاءة، ومعالجة الأخطاء، وكتابة كود نظيف.
1. الأساسيات: فتح وقراءة وكتابة الملفات
\n\nلنبدأ بأكثر العمليات شيوعًا. لفتح ملف، نستخدم الدالة os.OpenFile أو الدوال الأبسط os.Create و os.Open. لنلقِ نظرة على مثال لقراءة ملف كامل في الذاكرة:
package main\n\nimport (\n "fmt"\n "os"\n)\n\nfunc main() {\n // قراءة الملف بأكمله (قبل Go 1.16 كنا نستخدم ioutil.ReadFile)\n data, err := os.ReadFile("example.txt")\n if err != nil {\n fmt.Println("خطأ في قراءة الملف:", err)\n return\n }\n fmt.Println("محتوى الملف:")\n fmt.Println(string(data))\n}\n\n\nلكتابة البيانات إلى ملف، استخدم os.WriteFile:
package main\n\nimport (\n "os"\n)\n\nfunc main() {\n content := []byte("مرحبًا، عالم Go!\\nالسطر الثاني.")\n err := os.WriteFile("output.txt", content, 0644)\n if err != nil {\n panic(err)\n }\n // تم إنشاء ملف output.txt ويحتوي على نصنا\n}\n\n\nإذا كنت بحاجة إلى إضافة بيانات في نهاية الملف، استخدم العلامات:
\n\nfile, err := os.OpenFile("log.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)\nif err != nil {\n panic(err)\n}\ndefer file.Close()\n\nif _, err := file.WriteString("إدخال جديد في السجل\\n"); err != nil {\n panic(err)\n}\n\n\n2. العمل مع المجلدات: إنشاء وحذف وتصفح
\n\nإدارة المجلدات لا تقل أهمية. يمكن إنشاء مجلد جديد باستخدام os.Mkdir (مجلد واحد) أو os.MkdirAll (بشكل متكرر، مثل mkdir -p):
package main\n\nimport (\n "fmt"\n "os"\n)\n\nfunc main() {\n // إنشاء مجلد واحد\n err := os.Mkdir("data", 0755)\n if err != nil {\n fmt.Println("خطأ في إنشاء المجلد:", err)\n }\n\n // إنشاء هيكل متداخل بشكل متكرر\n err = os.MkdirAll("data/subdir/logs", 0755)\n if err != nil {\n fmt.Println("خطأ:", err)\n }\n}\n\n\nلتصفح مجلد، يمكن استخدام الدالة os.ReadDir (بديل ioutil.ReadDir):
entries, err := os.ReadDir(".")\nif err != nil {\n panic(err)\n}\n\nfor _, entry := range entries {\n fmt.Printf("الاسم: %s, مجلد: %t\\n", entry.Name(), entry.IsDir())\n}\n\n\nولتصفح جميع الملفات والمجلدات بشكل متكرر، استخدم filepath.Walk من الحزمة path/filepath:
package main\n\nimport (\n "fmt"\n "os"\n "path/filepath"\n)\n\nfunc main() {\n err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error {\n if err != nil {\n return err\n }\n fmt.Println(path)\n return nil\n })\n if err != nil {\n fmt.Println("خطأ في التصفح:", err)\n }\n}\n\n\nيتم حذف الملفات والمجلدات باستخدام الدالتين os.Remove و os.RemoveAll:
// حذف ملف واحد أو مجلد فارغ\nos.Remove("temp.txt")\n\n// حذف مجلد بكل محتوياته (مشابه لـ rm -rf)\nos.RemoveAll("data")\n\n\n3. تقنيات متقدمة: الإدخال/الإخراج المخزن والعمل مع الملفات المؤقتة
\n\nبالنسبة للملفات الكبيرة، قراءة المحتوى بالكامل في الذاكرة غير فعالة. استخدم القراءة المخزنة باستخدام bufio:
package main\n\nimport (\n "bufio"\n "