مقدمة: لماذا Go لـ REST API؟
\nGo (Golang) هي لغة حديثة ومترجمة مع دعم مدمج للتوازي (concurrency) وأداء عالٍ. REST API بلغة Go يعمل بسرعة، ويستهلك ذاكرة قليلة، ويسهل توسيعه. في 30 دقيقة، ستقوم بإنشاء خدمة REST كاملة مع طلبات GET و POST و PUT و DELETE باستخدام المكتبة القياسية فقط.
\nفي هذا الدليل، سنكتب API لإدارة قائمة المهام (تطبيق Todo). ستتعلم كيفية إعداد توجيه المسارات، ومعالجة JSON، وإضافة الوسائط الوسيطة لتسجيل السجلات، وإرجاع الأخطاء بشكل صحيح. بدون أطر عمل خارجية — فقط Go النقي!
\n\n1. إعداد المشروع وهيكله
\nأنشئ دليلاً جديداً للمشروع وقم بتهيئة وحدة Go:
\nmkdir go-todo-api\ncd go-todo-api\ngo mod init todo-api\nسيكون هيكل المشروع بسيطاً:
\n- \n
main.go— نقطة الدخول وتشغيل الخادم \nhandlers.go— معالجات الطلبات \nmodels.go— هياكل البيانات \nmiddleware.go— البرمجيات الوسيطة \n
أنشئ ملف models.go بهيكل المهمة:
package main\n\ntype Task struct {\n ID int `json:"id"`\n Title string `json:"title"`\n Completed bool `json:"completed"`\n}\nسنقوم بتخزين المهام في الذاكرة (شريحة tasks) للتبسيط. في مشروع حقيقي، استخدم قاعدة بيانات.
\n\n2. توجيه المسارات والمعالجات
\nتستخدم Go الحزمة المدمجة net/http. لننشئ ملف handlers.go مع المعالجات الأساسية.
2.1. GET /tasks — الحصول على جميع المهام
\npackage main\n\nimport (\n "encoding/json"\n "net/http"\n "strconv"\n)\n\nvar tasks = []Task{}\nvar nextID = 1\n\nfunc getTasks(w http.ResponseWriter, r *http.Request) {\n w.Header().Set("Content-Type", "application/json")\n json.NewEncoder(w).Encode(tasks)\n}\n2.2. POST /tasks — إنشاء مهمة جديدة
\nfunc createTask(w http.ResponseWriter, r *http.Request) {\n var newTask Task\n if err := json.NewDecoder(r.Body).Decode(&newTask); err != nil {\n http.Error(w, "Invalid JSON", http.StatusBadRequest)\n return\n }\n newTask.ID = nextID\n nextID++\n tasks = append(tasks, newTask)\n w.Header().Set("Content-Type", "application/json")\n w.WriteHeader(http.StatusCreated)\n json.NewEncoder(w).Encode(newTask)\n}\n2.3. PUT /tasks/{id} — تحديث مهمة
\nfunc updateTask(w http.ResponseWriter, r *http.Request) {\n idStr := r.PathValue("id")\n id, err := strconv.Atoi(idStr)\n if err != nil {\n http.Error(w, "Invalid task ID", http.StatusBadRequest)\n return\n }\n \n var updatedTask Task\n if err := json.NewDecoder(r.Body).Decode(&updatedTask); err != nil {\n http.Error(w, "Invalid JSON", http.StatusBadRequest)\n return\n }\n \n for i, t := range tasks {\n if t.ID == id {\n tasks[i].Title = updatedTask.Title\n tasks[i].Completed = updatedTask.Completed\n w.Header().Set("Content-Type", "application/json")\n json.NewEncoder(w).Encode(tasks[i])\n return\n }\n }\n http.Error(w, "Task not found", http.StatusNotFound)\n}\n2.4. DELETE /tasks/{id} — حذف مهمة
\nfunc deleteTask(w http.ResponseWriter, r *http.Request) {\n idStr := r.PathValue("id")\n id, err := strconv.Atoi(idStr)\n if err != nil {\n http.Error(w, "Invalid task ID", http.StatusBadRequest)\n return\n }\n \n for i, t := range tasks {\n if t.ID == id {\n tasks = append(tasks[:i], tasks[i+1:]...)\n w.WriteHeader(http.StatusNoContent)\n return\n }\n }\n http.Error(w, "Task not found", http.StatusNotFound)\n}\nلاحظ أن