Μετατρέψτε εντολές 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 υπερέχει στις γρήγορες ad-hoc δοκιμές και σενάρια.
Α: Η Go χρησιμοποιεί defer resp.Body.Close() για να διασφαλίσει ότι οι πόροι απελευθερώνονται σωστά ακόμα και αν προκύψουν σφάλματα αργότερα στη συνάρτηση. Αυτό το μοτίβο είναι ιδιωματικό στη Go και αποτρέπει τις διαρροές πόρων που θα μπορούσαν να συμβούν αν ξεχάσετε να κλείσετε το σώμα σε όλες τις πιθανές διαδρομές κώδικα.
Α: Αντί να χρησιμοποιείτε ioutil.ReadAll()
, μπορείτε να επεξεργαστείτε το σώμα της απόκρισης ως ροή χρησιμοποιώντας io.Copy()
ή διαβάζοντας τμήματα με ένα buffer. Αυτό είναι ιδιαίτερα χρήσιμο για μεγάλες αποκρίσεις όπου η φόρτωση ολόκληρου του σώματος στη μνήμη θα ήταν αναποτελεσματική.
Α: Ναι, και συνιστάται! Η δημιουργία ενός μοναδικού http.Client
και η επαναχρησιμοποίησή του σε διάφορα αιτήματα επιτρέπει τη συγκέντρωση συνδέσεων και βελτιώνει την απόδοση. Ο πελάτης είναι ασφαλής για ταυτόχρονη χρήση και μπορεί να μοιραστεί μεταξύ goroutines χωρίς πρόσθετο συγχρονισμό.
Α: Το πακέτο 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 ακολουθεί αυτόματα τις ανακατευθύνσεις (έως 10 από προεπιλογή), παρόμοια με το 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)