Einleitung: Warum es wichtig ist, mit HTTP in Go arbeiten zu können
\nGo (Golang) ist eine für die Netzwerkarbeit entwickelte Sprache. Seine Standardbibliothek net/http bietet leistungsstarke und flexible Werkzeuge zur Erstellung sowohl von Servern als auch von Clients. Viele Entwickler, insbesondere diejenigen, die von Skriptsprachen kommen, machen jedoch typische Fehler: Sie vergessen, den Antwortbody zu schließen, setzen keine Timeouts oder behandeln Fehler falsch.
In diesem Artikel werden wir die Erstellung eines HTTP-Clients in Go „von A bis Z“ durchgehen. Sie erfahren, wie Sie GET- und POST-Anfragen richtig senden, Header verwalten, Timeouts konfigurieren und Fehler behandeln. Alle Codebeispiele sind einsatzbereit.
\n\n1. Grundlagen: Client erstellen und erste GET-Anfrage
\nIn Go ist der HTTP-Client die Struktur http.Client. Sie können den globalen Client http.DefaultClient verwenden oder Ihren eigenen mit benutzerdefinierten Einstellungen erstellen. Beginnen wir mit einer einfachen GET-Anfrage.
package main\n\nimport (\n "fmt"\n "io"\n "net/http"\n "os"\n)\n\nfunc main() {\n // Verwenden des integrierten Clients\n resp, err := http.Get("https://api.example.com/data")\n if err != nil {\n fmt.Printf("Anfragefehler: %v\\n", err)\n os.Exit(1)\n }\n defer resp.Body.Close() // WICHTIG: Antwortbody immer schließen!\n\n // Antwortbody lesen\n body, err := io.ReadAll(resp.Body)\n if err != nil {\n fmt.Printf("Fehler beim Lesen der Antwort: %v\\n", err)\n os.Exit(1)\n }\n\n fmt.Printf("Status: %s\\n", resp.Status)\n fmt.Printf("Body: %s\\n", string(body))\n}\nWichtige Punkte:
\n- \n
- Schließen Sie immer
resp.Bodymitdefer. Andernfalls kommt es zu Ressourcenlecks (Verbindungen werden nicht in den Pool zurückgegeben). \n - Überprüfen Sie den Antwortstatus (
resp.StatusCode). Code 200 ist nicht der einzige Erfolgscode (es gibt 201, 204 usw.). \n io.ReadAllliest den gesamten Body in den Speicher. Verwenden Sie für große Antwortenio.Copyoder Streaming. \n
2. Fortgeschrittener Client: Timeouts, Header und benutzerdefinierte Einstellungen
\nDer globale Client hat standardmäßig keine Timeouts – dies kann zum Einfrieren des Programms führen. Erstellen Sie immer Ihren eigenen Client mit Einstellungen.
\n2.1. Client mit Timeout erstellen
\nclient := &http.Client{\n Timeout: 10 * time.Second, // Gesamt-Timeout für die gesamte Anfrage\n}\n\nresp, err := client.Get("https://api.example.com/data")\nSie können auch Timeouts auf verschiedenen Ebenen über Transport konfigurieren:
transport := &http.Transport{\n DialContext: (&net.Dialer{\n Timeout: 5 * time.Second, // Verbindungs-Timeout\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\n2.2. Hinzufügen von Headern und Parametern
\nVerwenden Sie für komplexe Anfragen http.NewRequest:
req, err := http.NewRequest("GET", "https://api.example.com/search", nil)\nif err != nil {\n log.Fatal(err)\n}\n\n// Header hinzufügen\nreq.Header.Set("Authorization", "Bearer your-token")\nreq.Header.Set("Accept", "application/json")\n\n// Query-Parameter hinzufügen\nq := req.URL.Query()\nq.Add("query", "golang")\nq.Add("page", "1")\nreq.URL.RawQuery = q.Encode()\n\nresp, err := client.Do(req)\n\n3. Arbeiten mit POST und anderen Methoden (JSON, Formulare)
\nPOST-Anfragen erfordern das Senden eines Bodys. Betrachten wir zwei gängige Formate: JSON und URL-kodierte Formulare.
\n3.1. POST mit JSON
\ntype RequestData struct {\n Name string `json:"name"`\n Email string `json:"email"`\n}\n\ndata := RequestData{\n Name: "Ivan",\n Email: "ivan@example.com",\n}\n\njsonData, err := json.Marshal(da