Einleitung: Warum Go für REST APIs?
\nGo (Golang) ist eine moderne, kompilierte Sprache mit integrierter Unterstützung für Nebenläufigkeit und hoher Leistung. Eine REST API in Go arbeitet schnell, verbraucht wenig Speicher und lässt sich leicht skalieren. In 30 Minuten erstellen Sie einen vollständigen REST-Dienst mit GET-, POST-, PUT- und DELETE-Anfragen, der nur die Standardbibliothek verwendet.
\nIn dieser Anleitung schreiben wir eine API zur Verwaltung einer Aufgabenliste (Todo-App). Sie erfahren, wie Sie das Routing einrichten, JSON verarbeiten, Middleware für die Protokollierung hinzufügen und Fehler korrekt zurückgeben. Ohne externe Frameworks – nur reines Go!
\n\n1. Projekteinrichtung und Struktur
\nErstellen Sie ein neues Verzeichnis für das Projekt und initialisieren Sie das Go-Modul:
\nmkdir go-todo-api\ncd go-todo-api\ngo mod init todo-api\nDie Projektstruktur ist einfach:
\n- \n
main.go– Einstiegspunkt und Serverstart \nhandlers.go– Anfrage-Handler \nmodels.go– Datenstrukturen \nmiddleware.go– Middleware \n
Erstellen Sie die Datei models.go mit der Aufgabenstruktur:
package main\n\ntype Task struct {\n ID int `json:"id"`\n Title string `json:"title"`\n Completed bool `json:"completed"`\n}\nWir speichern die Aufgaben der Einfachheit halber im Arbeitsspeicher (Slice tasks). Verwenden Sie in einem echten Projekt eine Datenbank.
\n\n2. Routing und Handler
\nGo verwendet das integrierte Paket net/http. Erstellen wir die Datei handlers.go mit den wichtigsten Handlern.
2.1. GET /tasks – Alle Aufgaben abrufen
\npackage main\n\nimport (\n "encoding/json"\n "net/http"\n "strconv"\n)\n\nvar tasks = []Task{}\nvar nextID = 1\n\nfunc getTasks(w http.ResponseWriter, r *http.Request) {\n w.Header().Set("Content-Type", "application/json")\n json.NewEncoder(w).Encode(tasks)\n}\n2.2. POST /tasks – Neue Aufgabe erstellen
\nfunc createTask(w http.ResponseWriter, r *http.Request) {\n var newTask Task\n if err := json.NewDecoder(r.Body).Decode(&newTask); err != nil {\n http.Error(w, "Invalid JSON", http.StatusBadRequest)\n return\n }\n newTask.ID = nextID\n nextID++\n tasks = append(tasks, newTask)\n w.Header().Set("Content-Type", "application/json")\n w.WriteHeader(http.StatusCreated)\n json.NewEncoder(w).Encode(newTask)\n}\n2.3. PUT /tasks/{id} – Aufgabe aktualisieren
\nfunc updateTask(w http.ResponseWriter, r *http.Request) {\n idStr := r.PathValue("id")\n id, err := strconv.Atoi(idStr)\n if err != nil {\n http.Error(w, "Invalid task ID", http.StatusBadRequest)\n return\n }\n \n var updatedTask Task\n if err := json.NewDecoder(r.Body).Decode(&updatedTask); err != nil {\n http.Error(w, "Invalid JSON", http.StatusBadRequest)\n return\n }\n \n for i, t := range tasks {\n if t.ID == id {\n tasks[i].Title = updatedTask.Title\n tasks[i].Completed = updatedTask.Completed\n w.Header().Set("Content-Type", "application/json")\n json.NewEncoder(w).Encode(tasks[i])\n return\n }\n }\n http.Error(w, "Task not found", http.StatusNotFound)\n}\n2.4. DELETE /tasks/{id} – Aufgabe löschen
\nfunc deleteTask(w http.ResponseWriter, r *http.Request) {\n idStr := r.PathValue("id")\n id, err := strconv.Atoi(idStr)\n if err != nil {\n http.Error(w, "Invalid task ID", http.StatusBadRequest)\n return\n }\n \n for i, t := range tasks {\n if t.ID == id {\n tasks = append(tasks[:i], tasks[i+1:]...)\n w.WriteHeader(http.StatusNoContent)\n return\n }\n }\n http.Error(w, "Task not found", http.StatusNotFound)\n}\nBeachten Sie