تبدیل دستورات curl به کد Go - تولید کد Go net/http آماده استفاده برای درخواستهای API
// Go code will appear here // Example: package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.example.com/data" // Create request payload payload := map[string]interface{}{ "name": "test", } jsonData, err := json.Marshal(payload) if err != nil { fmt.Println("Error marshaling JSON:", err) return } // Create request req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) if err != nil { fmt.Println("Error creating request:", err) return } // Add headers req.Header.Set("Content-Type", "application/json") // Send request client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Println("Error sending request:", err) return } defer resp.Body.Close() // Read response body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response:", err) return } fmt.Println("Status:", resp.Status) fmt.Println("Response:", string(body)) }
در اینجا برخی دستورات curl رایج که میتوانید به کد Go تبدیل کنید آمده است:
curl https://api.example.com/users
curl -X POST -H "Content-Type: application/json" -d '{"name":"John","email":"[email protected]"}' https://api.example.com/users
curl -X PUT -H "Authorization: Bearer token123" -d '{"status":"active"}' https://api.example.com/users/1
curl -X DELETE https://api.example.com/users/1
curl -H "X-API-Key: abc123" -H "Accept: application/json" https://api.example.com/data
بسته net/http در Go روشی قدرتمند و کارآمد برای ارسال درخواستهای HTTP فراهم میکند. در اینجا برخی الگوهای رایج HTTP Go آمده است:
package main import ( "bytes" "fmt" "io" "io/ioutil" "mime/multipart" "net/http" "os" "path/filepath" ) func main() { url := "https://api.example.com/upload" // Create a buffer to store the multipart form var requestBody bytes.Buffer multipartWriter := multipart.NewWriter(&requestBody) // Open the file file, err := os.Open("document.pdf") if err != nil { fmt.Println("Error opening file:", err) return } defer file.Close() // Create a form file field fileWriter, err := multipartWriter.CreateFormFile("file", filepath.Base("document.pdf")) if err != nil { fmt.Println("Error creating form file:", err) return } // Copy the file content to the form field _, err = io.Copy(fileWriter, file) if err != nil { fmt.Println("Error copying file to form:", err) return } // Add other form fields if needed multipartWriter.WriteField("description", "Sample document upload") // Close the multipart writer multipartWriter.Close() // Create request req, err := http.NewRequest("POST", url, &requestBody) if err != nil { fmt.Println("Error creating request:", err) return } // Set the content type with the boundary req.Header.Set("Content-Type", multipartWriter.FormDataContentType()) req.Header.Set("Authorization", "Bearer YOUR_TOKEN_HERE") // Send request client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Println("Error sending request:", err) return } defer resp.Body.Close() // Read response body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response:", err) return } fmt.Println("Status:", resp.Status) fmt.Println("Response:", string(body)) }
package main import ( "context" "encoding/json" "fmt" "io/ioutil" "net/http" "time" ) func main() { // Create a context with timeout ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Create request req, err := http.NewRequestWithContext(ctx, "GET", "https://api.example.com/data", nil) if err != nil { fmt.Println("Error creating request:", err) return } // Send request client := &http.Client{} resp, err := client.Do(req) // Handle errors if err != nil { if ctx.Err() == context.DeadlineExceeded { fmt.Println("Request timed out") } else { fmt.Println("Error sending request:", err) } return } defer resp.Body.Close() // Check status code if resp.StatusCode != http.StatusOK { fmt.Printf("Server returned non-200 status: %s\n", resp.Status) body, _ := ioutil.ReadAll(resp.Body) fmt.Println("Response body:", string(body)) return } // Read and parse response var data map[string]interface{} body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response:", err) return } err = json.Unmarshal(body, &data) if err != nil { fmt.Println("Error parsing JSON:", err) fmt.Println("Raw response:", string(body)) return } fmt.Println("Successfully received data:", data) }
دستور curl خود را کپی کنید → در کادر ورودی جایگذاری کنید → فوراً کد Go دریافت کنید
// Always check for errors in Go resp, err := client.Do(req) if err != nil { fmt.Println("Error sending request:", err) return } defer resp.Body.Close() // Check status code if resp.StatusCode != http.StatusOK { fmt.Printf("Server returned non-200 status: %s\n", resp.Status) body, _ := ioutil.ReadAll(resp.Body) fmt.Println("Response body:", string(body)) return }
// Create a context with timeout ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Create request with context req, err := http.NewRequestWithContext(ctx, "GET", "https://api.example.com/data", nil) if err != nil { fmt.Println("Error creating request:", err) return } // Send request client := &http.Client{} resp, err := client.Do(req) // Check for timeout if err != nil { if ctx.Err() == context.DeadlineExceeded { fmt.Println("Request timed out") } else { fmt.Println("Error sending request:", err) } return }
ج: در حالی که curl یک ابزار خط فرمان برای ارسال درخواستهای HTTP است، بسته net/http در Go یک API برنامهنویسی ارائه میدهد. Go تایپ قویتر، پشتیبانی از همزمانی داخلی و ادغام بهتر با کد برنامه شما را ارائه میدهد، در حالی که curl در تستهای موردی سریع و اسکریپتنویسی برتری دارد.
ج: Go از defer resp.Body.Close() استفاده میکند تا اطمینان حاصل شود که منابع حتی در صورت بروز خطا در ادامه تابع، به درستی آزاد میشوند. این الگو در Go متداول است و از نشت منابعی که ممکن است در صورت فراموش کردن بستن بدنه در تمام مسیرهای کد ممکن رخ دهد، جلوگیری میکند.
ج: به جای استفاده از ioutil.ReadAll()
، میتوانید بدنه پاسخ را به صورت جریانی با استفاده از io.Copy()
یا با خواندن قطعات با یک بافر پردازش کنید. این به ویژه برای پاسخهای بزرگ که بارگذاری کل بدنه در حافظه ناکارآمد خواهد بود، مفید است.
ج: بله، و این توصیه میشود! ایجاد یک http.Client
واحد و استفاده مجدد از آن در درخواستهای مختلف امکان استخر اتصال و بهبود عملکرد را فراهم میکند. کلاینت برای همزمانی ایمن است و میتواند بدون نیاز به همگامسازی اضافی بین goroutineها به اشتراک گذاشته شود.
ج: بسته context در Go امکان لغو درخواست را به شکلی زیبا فراهم میکند. یک context با context.WithCancel()
یا context.WithTimeout()
ایجاد کنید، سپس آن را به http.NewRequestWithContext()
منتقل کنید. میتوانید درخواست را در هر زمان با فراخوانی تابع لغو، لغو کنید.
ج: برای رد کردن تأیید گواهی TLS (مانند پرچم -k در curl)، یک Transport سفارشی در کلاینت HTTP خود پیکربندی کنید: client := &http.Client{Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}}
با این حال، این باید فقط برای تست استفاده شود، زیرا بررسیهای امنیتی را دور میزند.
ج: کلاینت HTTP در Go به طور خودکار تغییر مسیرها را دنبال میکند (تا ۱۰ مورد به طور پیشفرض)، مشابه curl. برای سفارشیسازی این رفتار، یک تابع CheckRedirect
سفارشی در کلاینت HTTP خود تنظیم کنید تا مدیریت تغییر مسیر را کنترل کنید یا کاملاً از تغییر مسیرها جلوگیری کنید.
درک دستورات curl برای تست مؤثر API در Go ضروری است. در اینجا مرجع سریعی از گزینههای رایج curl که مبدل ما پشتیبانی میکند آمده است:
curl [options] [URL]
-X, --request METHOD
: Specify request method (GET, POST, PUT, DELETE, etc.)-H, --header LINE
: Add header to the request-d, --data DATA
: Send data in POST request-F, --form CONTENT
: Submit form data-u, --user USER:PASSWORD
: Server user and password-k, --insecure
: Allow insecure server connections-I, --head
: Show document info only-v, --verbose
: Make the operation more verbose-s, --silent
: Silent mode--connect-timeout SECONDS
: Maximum time for connectionمبدل Go ما دستورات پیچیده curl شامل چندین هدر، احراز هویت، دادههای محتوا و گزینههای مختلف را پشتیبانی میکند. به سادگی دستور curl خود را جایگذاری کنید و کد Go تمیز و مدرن با استفاده از بسته net/http دریافت کنید.
هنگام کار با بسته net/http در Go، این بهترین شیوهها را برای تعاملات API کارآمد و امن دنبال کنید:
resp, err := client.Do(req) if err != nil { fmt.Println("Error sending request:", err) return } defer resp.Body.Close() // Important: prevents resource leaks
client := &http.Client{ Timeout: 10 * time.Second, Transport: &http.Transport{ MaxIdleConns: 100, MaxIdleConnsPerHost: 20, IdleConnTimeout: 90 * time.Second, }, } resp, err := client.Do(req) if err != nil { fmt.Println("Error sending request:", err) return }
resp, err := client.Do(req) if err != nil { var netErr net.Error if errors.As(err, &netErr) && netErr.Timeout() { fmt.Println("Request timed out") } else if errors.Is(err, context.DeadlineExceeded) { fmt.Println("Context deadline exceeded") } else { fmt.Println("Error sending request:", err) } return } defer resp.Body.Close() // Check status code if resp.StatusCode < 200 || resp.StatusCode >= 300 { body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("Error status: %d %s\n", resp.StatusCode, resp.Status) fmt.Printf("Response body: %s\n", string(body)) return } // Read response body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response body:", err) return } // Process response data var result map[string]interface{} if err := json.Unmarshal(body, &result); err != nil { fmt.Println("Error parsing JSON:", err) fmt.Println("Raw response:", string(body)) return }
// Create context with timeout ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Important: prevents context leaks // Create request with context req, err := http.NewRequestWithContext(ctx, "GET", "https://api.example.com/data", nil) if err != nil { fmt.Println("Error creating request:", err) return } // Send request resp, err := client.Do(req) // Error handling...
// Define request and response structs type User struct { ID int `json:"id,omitempty"` Name string `json:"name"` Email string `json:"email"` } // Create request data user := User{ Name: "John Doe", Email: "[email protected]", } // Serialize to JSON jsonData, err := json.Marshal(user) if err != nil { fmt.Println("Error marshaling JSON:", err) return } // Create request req, err := http.NewRequest("POST", "https://api.example.com/users", bytes.NewBuffer(jsonData)) // Set headers, send request, etc... // Deserialize response var responseUser User if err := json.Unmarshal(body, &responseUser); err != nil { fmt.Println("Error parsing JSON response:", err) return } fmt.Printf("Created user with ID: %d\n", responseUser.ID)