كيفية كتابة REST API بلغة Go في 30 دقيقة: دليل عملي

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا Go لـ REST API؟

\n

Go (Golang) هي لغة حديثة ومترجمة مع دعم مدمج للتوازي (concurrency) وأداء عالٍ. REST API بلغة Go يعمل بسرعة، ويستهلك ذاكرة قليلة، ويسهل توسيعه. في 30 دقيقة، ستقوم بإنشاء خدمة REST كاملة مع طلبات GET و POST و PUT و DELETE باستخدام المكتبة القياسية فقط.

\n

في هذا الدليل، سنكتب API لإدارة قائمة المهام (تطبيق Todo). ستتعلم كيفية إعداد توجيه المسارات، ومعالجة JSON، وإضافة الوسائط الوسيطة لتسجيل السجلات، وإرجاع الأخطاء بشكل صحيح. بدون أطر عمل خارجية — فقط Go النقي!

\n\n

1. إعداد المشروع وهيكله

\n

أنشئ دليلاً جديداً للمشروع وقم بتهيئة وحدة Go:

\n
mkdir go-todo-api\ncd go-todo-api\ngo mod init todo-api
\n

سيكون هيكل المشروع بسيطاً:

\n
    \n
  • main.go — نقطة الدخول وتشغيل الخادم
  • \n
  • handlers.go — معالجات الطلبات
  • \n
  • models.go — هياكل البيانات
  • \n
  • middleware.go — البرمجيات الوسيطة
  • \n
\n

أنشئ ملف models.go بهيكل المهمة:

\n
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\n

2. توجيه المسارات والمعالجات

\n

تستخدم Go الحزمة المدمجة net/http. لننشئ ملف handlers.go مع المعالجات الأساسية.

\n

2.1. GET /tasks — الحصول على جميع المهام

\n
package 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}
\n

2.2. POST /tasks — إنشاء مهمة جديدة

\n
func 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}
\n

2.3. PUT /tasks/{id} — تحديث مهمة

\n
func 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}
\n

2.4. DELETE /tasks/{id} — حذف مهمة

\n
func 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

لاحظ أن

المدونات

توصيات الكتب