عميل HTTP بلغة Go: إجراء الطلبات بشكل صحيح

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

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

ابدأ الدورة

مقدمة

Go (Golang) هي لغة حديثة ومترجمة من Google، وهي مثالية لبناء خدمات شبكية عالية التحميل. توفر الحزمة المدمجة net/http عميل HTTP قوي ومرن يسمح بالتفاعل بسهولة مع REST API وخوادم الويب وموارد HTTP الأخرى. ومع ذلك، على الرغم من البساطة الظاهرية، غالبًا ما يرتكب المبتدئون أخطاء نموذجية: نسيان إغلاق جسم الاستجابة، عدم معالجة المهلات الزمنية، أو تجاهل الأخطاء.

في هذه المقالة، سنشرح كيفية استخدام عميل HTTP بشكل صحيح في Go. ستتعلم كيفية إجراء طلبات GET و POST، وإدارة الرؤوس (Headers)، وضبط المهلات الزمنية، ومعالجة الأخطاء. جميع أمثلة الكود جاهزة للاستخدام في مشاريعك.

1. الأساسيات: طلب GET وقراءة الاستجابة

أبسط طريقة لتنفيذ طلب GET هي استخدام الدالة http.Get(). ومع ذلك، بالنسبة لرمز الإنتاج، يُوصى بإنشاء نسخة خاصة بك من http.Client — فهذا يمنحك تحكمًا أكبر في سلوك العميل.

طلب GET بسيط

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
)

func main() {
    // إنشاء عميل (حاليًا بالإعدادات الافتراضية)
    client := &http.Client{}
    
    // تنفيذ طلب GET
    resp, err := client.Get("https://api.example.com/data")
    if err != nil {
        fmt.Fprintf(os.Stderr, "خطأ في الطلب: %v", err)
        os.Exit(1)
    }
    // مهم: إغلاق جسم الاستجابة
    defer resp.Body.Close()

    // قراءة جسم الاستجابة
    body, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Fprintf(os.Stderr, "خطأ في قراءة الجسم: %v", err)
        os.Exit(1)
    }

    fmt.Printf("الحالة: %s", resp.Status)
    fmt.Printf("الجسم: %s", body)
}

النقاط الرئيسية:

  • defer resp.Body.Close() — تأكد من إغلاق جسم الاستجابة، وإلا سيحدث تسرب للموارد (لن يعود الاتصال إلى المجموعة).
  • تحقق دائمًا من err — الشبكة غير مستقرة، وقد يفشل الطلب.
  • تحقق من حالة HTTP للاستجابة (resp.StatusCode) لتمييز النجاح (2xx) عن أخطاء الخادم (4xx, 5xx).

2. طلب POST مع جسم ورؤوس (Headers)

لإرسال بيانات إلى الخادم (مثل JSON)، يتم استخدام http.Post() أو الطريقة الأكثر مرونة http.NewRequest() متبوعة باستدعاء client.Do(). الطريقة الثانية هي المفضلة لأنها تسمح بتعيين الرؤوس والمعلمات الأخرى.

POST مع بيانات JSON

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
    "os"
)

type User struct {
    Name  string `json:"name"`
    Email string `json:"email"`
}

func main() {
    client := &http.Client{}

    // تحضير البيانات
    user := User{Name: "إيفان بيتروف", Email: "ivan@example.com"}
    jsonData, err := json.Marshal(user)
    if err != nil {
        fmt.Fprintf(os.Stderr, "خطأ في تسلسل JSON: %v", err)
        os.Exit(1)
    }

    // إنشاء الطلب
    req, err := http.NewRequest("POST", "https://api.example.com/users", bytes.NewBuffer(jsonData))
    if err != nil {
        fmt.Fprintf(os.Stderr, "خطأ في إنشاء الطلب: %v", err)
        os.Exit(1)
    }

    // تعيين الرؤوس
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Authorization", "Bearer YOUR_TOKEN_HERE")

    // إرسال الطلب
    resp, err := client.Do(req)
    if err != nil {
        fmt.Fprintf(os.Stderr, "خطأ في الطلب: %v", err)
        os.Exit(1)
    }
    defer resp.Body.Close()

    // التحقق من الحالة
    if resp.StatusCode != http.StatusCreated {
        fmt.Fprintf(os.Stderr, "الخادم أرجع خطأ: %s", resp.Status)
        os.Exit(1)
    }

    fmt.Println("تم إنشاء المستخدم بنجاح!")
}

مهم:

المدونات

توصيات الكتب