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

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

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

ابدأ الدورة

مقدمة: لماذا من المهم إتقان العمل مع HTTP في Go

\n

Go (Golang) هي لغة مصممة للعمل في الشبكات. توفر مكتبتها القياسية net/http أدوات قوية ومرنة لإنشاء كل من الخوادم والعملاء. ومع ذلك، يرتكب العديد من المطورين، خاصة القادمين من لغات البرمجة النصية، أخطاء نموذجية: ينسون إغلاق جسم الاستجابة، ولا يحددون مهلات، أو يعالجون الأخطاء بشكل غير صحيح.

\n

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

\n\n

1. الأساسيات: إنشاء عميل وأول طلب GET

\n

في Go، عميل HTTP هو هيكل http.Client. يمكنك استخدام العميل العام http.DefaultClient أو إنشاء عميل خاص بك مع إعدادات مخصصة. لنبدأ بطلب GET بسيط.

\n
package main\n\nimport (\n    "fmt"\n    "io"\n    "net/http"\n    "os"\n)\n\nfunc main() {\n    // استخدام العميل المدمج\n    resp, err := http.Get("https://api.example.com/data")\n    if err != nil {\n        fmt.Printf("خطأ في الطلب: %v\\n", err)\n        os.Exit(1)\n    }\n    defer resp.Body.Close() // هام: أغلق جسم الاستجابة دائمًا!\n\n    // قراءة جسم الاستجابة\n    body, err := io.ReadAll(resp.Body)\n    if err != nil {\n        fmt.Printf("خطأ في قراءة الاستجابة: %v\\n", err)\n        os.Exit(1)\n    }\n\n    fmt.Printf("الحالة: %s\\n", resp.Status)\n    fmt.Printf("الجسم: %s\\n", string(body))\n}
\n

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

\n
    \n
  • أغلق resp.Body دائمًا باستخدام defer. وإلا سيحدث تسرب للموارد (لن تعود الاتصالات إلى المجموعة).
  • \n
  • تحقق من حالة الاستجابة (resp.StatusCode). الكود 200 ليس النجاح الوحيد (هناك 201، 204، إلخ).
  • \n
  • io.ReadAll يقرأ الجسم بالكامل في الذاكرة. للاستجابات الكبيرة، استخدم io.Copy أو المعالجة التدفقية.
  • \n
\n\n

2. عميل متقدم: المهلات والرؤوس والإعدادات المخصصة

\n

العميل العام ليس لديه مهلات افتراضية - وهذا قد يؤدي إلى تجميد البرنامج. أنشئ عميلك الخاص دائمًا مع الإعدادات.

\n

2.1. إنشاء عميل بمهلة

\n
client := &http.Client{\n    Timeout: 10 * time.Second, // مهلة إجمالية للطلب بأكمله\n}\n\nresp, err := client.Get("https://api.example.com/data")
\n

يمكنك أيضًا ضبط المهلات على مستويات مختلفة من خلال Transport:

\n
transport := &http.Transport{\n    DialContext: (&net.Dialer{\n        Timeout:   5 * time.Second, // مهلة الاتصال\n        KeepAlive: 30 * time.Second,\n    }).DialContext,\n    TLSHandshakeTimeout:   5 * time.Second,\n    ResponseHeaderTimeout: 5 * time.Second,\n}\n\nclient := &http.Client{\n    Transport: transport,\n    Timeout:   15 * time.Second,\n}
\n\n

2.2. إضافة الرؤوس والمعاملات

\n

للطلبات المعقدة، استخدم http.NewRequest:

\n
req, err := http.NewRequest("GET", "https://api.example.com/search", nil)\nif err != nil {\n    log.Fatal(err)\n}\n\n// إضافة الرؤوس\nreq.Header.Set("Authorization", "Bearer your-token")\nreq.Header.Set("Accept", "application/json")\n\n// إضافة معاملات الاستعلام\nq := req.URL.Query()\nq.Add("query", "golang")\nq.Add("page", "1")\nreq.URL.RawQuery = q.Encode()\n\nresp, err := client.Do(req)
\n\n

3. العمل مع POST والطرق الأخرى (JSON، النماذج)

\n

تتطلب طلبات POST إرسال جسم. سننظر في تنسيقين شائعين: JSON والنموذج المشفر بعنوان URL.

\n

3.1. POST مع JSON

\n
type RequestData struct {\n    Name  string `json:"name"`\n    Email string `json:"email"`\n}\n\ndata := RequestData{\n    Name:  "إيفان",\n    Email: "ivan@example.com",\n}\n\njsonData, err := json.Marshal(da                

المدونات

توصيات الكتب