KoderKoder.ai
PreiseEnterpriseBildungFür Investoren
AnmeldenLoslegen

Produkt

PreiseEnterpriseFür Investoren

Ressourcen

Kontakt aufnehmenSupportBildungBlog

Rechtliches

DatenschutzrichtlinieNutzungsbedingungenSicherheitRichtlinie zur akzeptablen NutzungMissbrauch melden

Soziales

LinkedInTwitter
Koder.ai
Sprache

© 2026 Koder.ai. Alle Rechte vorbehalten.

Startseite›Blog›Claude Code für Go-API-Scaffolding: konsistente Handler und Services
01. Jan. 2026·6 Min

Claude Code für Go-API-Scaffolding: konsistente Handler und Services

Claude Code für Go‑API‑Scaffolding: Definiere ein sauberes Handler‑Service‑Fehler‑Muster und generiere neue Endpunkte, die in deiner Go‑API konsistent bleiben.

Claude Code für Go-API-Scaffolding: konsistente Handler und Services

Warum Go-APIs chaotisch werden, wenn Muster nicht früh festgelegt werden

Go‑APIs starten meist sauber: ein paar Endpunkte, ein oder zwei Personen, und alles lebt in den Köpfen. Dann wächst die API, Features werden unter Zeitdruck geliefert und kleine Unterschiede schleichen sich ein. Jeder für sich fühlt sich harmlos an, zusammen verlangsamen sie jede spätere Änderung.

Ein häufiges Beispiel: Ein Handler dekodiert JSON in ein Struct und gibt 400 mit einer hilfreichen Nachricht zurück, ein anderer gibt 422 mit anderer Form zurück, und ein dritter loggt Fehler in anderem Format. Nichts davon bricht die Kompilierung. Es erzeugt aber dauernde Entscheidungsfindung und kleine Umschreibungen bei jedem neuen Endpoint.

Den Schlamassel spürst du an Stellen wie:

  • Unterschiedliche Fehler‑Bodies über Endpunkte hinweg, sodass Clients Sonderfälle brauchen.
  • Services, die mal rohe Datenbankfehler zurückgeben und mal „freundliche“.
  • Namensdrift (CreateUser, AddUser, RegisterUser), die die Suche erschwert.
  • Validierung, die hin und her wandert, sodass dieselben Bugs wiederkommen.

„Scaffolding“ bedeutet hier eine wiederholbare Vorlage für neue Arbeit: wohin Code gehört, was jede Schicht macht und wie Antworten aussehen. Es geht weniger ums massenhafte Generieren von Code als darum, eine konsistente Form festzusetzen.

Tools wie Claude können helfen, neue Endpunkte schnell zu generieren, aber sie bleiben nur nützlich, wenn du das Muster als Regel behandelst. Du definierst die Regeln, reviewst jeden Diff und fährst Tests. Das Modell füllt die Standardteile aus; es darf deine Architektur nicht neu definieren.

Wähle eine Schichtaufteilung: Handler, Service und Data Access

Eine Go‑API bleibt leicht zu erweitern, wenn jede Anfrage denselben Pfad folgt. Bevor du Endpunkte generierst, wähle eine Schichtaufteilung und halte dich daran.

Zuständigkeiten, einfach gehalten

Die Aufgabe des Handlers ist ausschließlich HTTP: Anfrage lesen, Service aufrufen und Antwort schreiben. Er sollte keine Business‑Regeln, kein SQL und kein „nur dieser eine Spezialfall“ enthalten.

Der Service verantwortet den Use Case: Geschäftsregeln, Entscheidungen und Orchestrierung über Repositories oder externe Aufrufe. Er sollte nichts über HTTP‑Belange wissen wie Statuscodes, Header oder wie Fehler gerendert werden.

Data Access (Repository/Store) kümmert sich um Persistenzdetails. Er übersetzt Service‑Intention in SQL/Queries/Transaktionen. Er darf Geschäftsregeln nur soweit durchsetzen, wie es die Datenintegrität verlangt, und soll keine API‑Antworten formen.

Eine praktische Trennungsliste:

  • Handler: Input parsen, Service aufrufen, Fehler auf HTTP mappen, JSON schreiben
  • Service: Geschäftsregeln anwenden, Repos aufrufen, Domain‑Ergebnisse oder typisierte Fehler zurückgeben
  • Data Access: Queries ausführen, Rows auf Structs mappen, Storage‑Fehler zurückgeben
  • Shared: gemeinsame Fehlertypen und Response‑Helfer
  • Keine Schicht überspringen (Handler ruft niemals direkt Repo auf)

Eine Regel für Validierung

Wähle eine Regel und biege sie nicht.

Ein einfacher Ansatz:

  • Handler machen „Shape‑Validation“ (erforderliche Felder, Basis‑Format)
  • Services machen „Meaning‑Validation“ (Permissions, Invarianten, Zustand)

Beispiel: Der Handler prüft, dass email vorhanden ist und wie eine E‑Mail aussieht. Der Service prüft, dass die E‑Mail erlaubt ist und noch nicht verwendet wird.

Was zwischen Schichten wandert

Entscheide früh, ob Services Domain‑Typen oder DTOs zurückgeben.

Eine saubere Voreinstellung ist: Handler benutzen Request/Response‑DTOs, Services Domain‑Typen, und der Handler mapped Domain → Response. Das hält den Service stabil, auch wenn sich der HTTP‑Vertrag ändert.

Wenn das Mapping sich schwerfällig anfühlt, halte trotzdem die Konsistenz: Der Service gibt einen Domain‑Typ plus einen typisierten Fehler zurück, und das JSON‑Shaping bleibt im Handler.

Definiere eine standardisierte Fehler‑Antwort und Statuscode‑Map

Wenn generierte Endpunkte so aussehen sollen, als wären sie von derselben Person geschrieben worden, sperre Fehler‑Antworten früh ein. Generierung funktioniert am besten, wenn das Ausgabeformat nicht verhandelbar ist: eine JSON‑Form, eine Statuscode‑Map und eine Regel, was offengelegt wird.

Beginne mit einer einzigen Fehler‑Hülle, die jeder Endpunkt bei Fehlern zurückgibt. Halte sie klein und vorhersehbar:

{
  "code": "validation_failed",
  "message": "One or more fields are invalid.",
  "details": {
    "fields": {
      "email": "must be a valid email address",
      "age": "must be greater than 0"
    }
  },
  "request_id": "req_01HR..."
}

Verwende code für Maschinen (stabil und vorhersehbar) und message für Menschen (kurz und sicher). Packe optionale strukturierte Daten in details. Für Validierung ist eine einfache details.fields‑Map leicht zu generieren und einfach für Clients, neben Eingaben angezeigt zu werden.

Schreibe dann eine Statuscode‑Map und halte dich daran. Je weniger Diskussion pro Endpoint, desto besser. Wenn du sowohl 400 als auch 422 willst, mache die Trennung explizit:

  • bad_json -> 400 Bad Request (malformed JSON)
  • validation_failed -> 422 Unprocessable Content (wohlgeformtes JSON, ungültige Felder)
  • not_found -> 404 Not Found
  • conflict -> 409 Conflict (duplizierter Schlüssel, Versionskonflikt)
  • unauthorized -> 401 Unauthorized
  • forbidden -> 403 Forbidden
  • internal -> 500 Internal Server Error

Entscheide, was du loggst vs. was du zurückgibst. Eine gute Regel: Clients bekommen eine sichere Nachricht und eine request_id; Logs enthalten den vollständigen Fehler und internen Kontext (SQL, Upstream‑Payloads, User‑IDs), den du niemals leaken würdest.

Standardisiere schließlich request_id. Akzeptiere eine eingehende ID‑Header, falls vorhanden (z. B. vom API‑Gateway), andernfalls generiere eine am Edge (Middleware). Hänge sie an den Context, füge sie den Logs bei und gib sie in jeder Fehlerantwort zurück.

Ordnerstruktur und Namensgebung, die Generierung vorhersehbar macht

Wenn Scaffolding konsistent bleiben soll, muss deine Ordnerstruktur langweilig und wiederholbar sein. Generatoren folgen Mustern, die sie erkennen können; sie driftet, wenn Dateien verstreut sind oder Namen pro Feature variieren.

Wähle eine Namenskonvention und halte dich daran. Verwende ein Wort für jede Sache: handler, service, repo, request, response. Wenn die Route POST /users heißt, benenne Dateien und Typen rund um users und create (nicht mal register, mal addUser).

Ein einfaches Layout, das die üblichen Schichten widerspiegelt:

internal/
  httpapi/
    handlers/
    users_handler.go
  services/
    users_service.go
  data/
    users_repo.go
  apitypes/
    users_types.go

Entscheide, wo Shared‑Typen leben, denn hier wird es oft unordentlich. Eine nützliche Regel:

  • API Request/Response‑Typen leben in internal/apitypes (passen zu JSON und Validierung)
  • Domain‑Typen leben näher an der Service‑Schicht (passen zu Geschäftsregeln)

Wenn ein Typ JSON‑Tags hat und für Clients gedacht ist, behandle ihn als API‑Typ.

Halte Handler‑Dependencies minimal und mache die Regel explizit:

  • Handler importieren nur: routing/http, context, apitypes und services
  • Services importieren: Domain‑Typen und Data Access
  • Data Access importiert: DB‑Driver und Query‑Hilfen
  • Kein Handler importiert das Datenbankpaket direkt

Schreibe ein kurzes Pattern‑Dokument in die Repo‑Root (Plain Markdown reicht). Füge den Ordnerbaum, Namensregeln und einen kleinen Beispiel‑Flow bei (handler -> service -> repo, plus in welcher Datei jedes Stück liegt). Das ist die Referenz, die du in deinen Generator kopierst, damit neue Endpunkte jedes Mal dieselbe Struktur haben.

Erstelle einen Referenz‑Endpoint, der das Muster setzt

Set up a clean Go backend
Build a Go + PostgreSQL backend with a consistent folder layout from day one.
Create Project

Bevor du zehn Endpunkte generierst, erstelle einen Endpoint, dem du vertraust. Das ist der Goldstandard: die Datei, auf die du zeigen kannst und sagst: „Neuer Code muss so aussehen.“ Du kannst ihn neu schreiben oder einen bestehenden refaktorieren, bis er passt.

Halte den Handler dünn. Eine kleine Maßnahme, die hilft: lege ein Interface zwischen Handler und Service, sodass der Handler von einem Vertrag abhängt, nicht von einer konkreten Implementierung.

Füge nur kurze Kommentare im Referenz‑Endpoint dort hinzu, wo generierter Code stolpern könnte. Erkläre Entscheidungen (warum 400 vs 422, warum create 201 zurückgibt, warum interne Fehler hinter einer generischen Nachricht verborgen werden). Überspringe Kommentare, die nur den Code wiederholen.

Wenn der Referenz‑Endpoint funktioniert, extrahiere Helfer, sodass jeder neue Endpoint weniger Chancen zum Driften hat. Die wiederverwendbarsten Helfer sind meist:

  • JSON binden und malformed bodies behandeln
  • Input validieren und Feldfehler zurückgeben
  • JSON‑Responses konsistent schreiben
  • Domain‑Fehler auf HTTP‑Statuscodes mappen

So kann ein „dünner Handler + Interface“ in der Praxis aussehen:

type UserService interface {
	CreateUser(ctx context.Context, in CreateUserInput) (User, error)
}

func (h *Handler) CreateUser(w http.ResponseWriter, r *http.Request) {
	var in CreateUserRequest
	if err := BindJSON(r, &in); err != nil {
		WriteError(w, ErrBadJSON) // 400: malformed JSON
		return
	}
	if err := Validate(in); err != nil {
		WriteError(w, err) // 422: validation details
		return
	}
	user, err := h.svc.CreateUser(r.Context(), in.ToInput())
	if err != nil {
		WriteError(w, err)
		return
	}
	WriteJSON(w, http.StatusCreated, user)
}

Verankere das mit ein paar Tests (selbst ein kleines Table‑Test für Error‑Mapping reicht). Generierung funktioniert am besten, wenn sie ein sauberes Ziel hat, das sie imitieren soll.

Schritt für Schritt: Claude einen neuen Endpoint passend erzeugen lassen

Konsistenz beginnt mit dem, was du einfügst, und dem, was du verbietest. Für einen neuen Endpoint gib zwei Dinge:

  1. Deinen Referenz‑Endpoint (das „perfekte“ Beispiel)
  2. Eine kurze Pattern‑Notiz, die Pakete, Funktionen und Helfer benennt, denen gefolgt werden muss

1) Kontext zuerst (Referenz + Regeln)

Füge Handler, Service‑Methode, Request/Response‑Typen und alle Shared‑Helfer bei, die der Endpoint nutzt. Dann formuliere den Vertrag in klaren Worten:

  • Route + Methode (z. B. POST /v1/widgets)
  • Request JSON‑Felder (required vs optional)
  • Response JSON‑Shape
  • Fehlerfälle und Statuscodes
  • Dateien, die du zurückerwartest (und nur diese)

Sei explizit, was übereinstimmen muss: Namensgebung, Paketpfade und Helfer (WriteJSON, BindJSON, WriteError, dein Validator).

2) Fordere eine Ausgabe in der genauen Form

Ein strikter Prompt verhindert „hilfreiche“ Refactorings. Zum Beispiel:

Using the reference endpoint below and the pattern notes, generate a new endpoint.
Contract:
- Route: POST /v1/widgets
- Request: {"name": string, "color": string}
- Response: {"id": string, "name": string, "color": string, "createdAt": string}
- Errors: invalid JSON -> 400; validation -> 422; duplicate name -> 409; unexpected -> 500
Output ONLY these files:
1) internal/http/handlers/widgets_create.go
2) internal/service/widgets.go (add method only)
3) internal/types/widgets.go (add types only)
Do not change: router setup, existing error format, existing helpers, or unrelated files.
Must use: package paths and helper functions exactly as in the reference.

Wenn du Tests möchtest, fordere sie explizit an (und benenne die Testdatei). Ansonsten könnte das Modell sie überspringen oder ein Test‑Setup erfinden.

Mache nach der Generierung einen schnellen Diff‑Check. Wenn gemeinsame Helfer, Router‑Registrierung oder dein Standard‑Error‑Format verändert wurden, lehne die Ausgabe ab und setze die „do not change“‑Regeln strenger.

Eine wiederverwendbare Prompt‑Vorlage für konsistente Endpoint‑Scaffolds

Die Ausgabe ist nur so konsistent wie die Eingabe. Der schnellste Weg, „fast fast richtig“ Code zu vermeiden, ist, dieselbe Prompt‑Vorlage immer wieder zu verwenden und ein kleines Kontext‑Snapshot aus deinem Repo beizufügen.

Prompt‑Vorlage

Kopiere, fülle die Platzhalter und verwende sie:

You are editing an existing Go HTTP API.

CONTEXT
- Folder tree (only the relevant parts):
  <paste a small tree: internal/http, internal/service, internal/repo, etc>
- Key types and patterns:
  - Handler signature style: <example>
  - Service interface style: <example>
  - Request/response DTOs live in: <package>
- Standard error response JSON:
  {
    "error": {
      "code": "invalid_argument",
      "message": "...",
      "details": {"field": "reason"}
    }
  }
- Status code map:
  invalid_json -> 400
  invalid_argument -> 422
  not_found -> 404
  conflict -> 409
  internal -> 500

TASK
Add a new endpoint: <METHOD> <PATH>
- Handler name: <Name>
- Service method: <Name>
- Request JSON example:
  {"name":"Acme"}
- Success response JSON example:
  {"id":"123","name":"Acme"}

CONSTRAINTS
- No new dependencies.
- Keep functions small and single-purpose.
- Match existing naming, folder layout, and error style exactly.
- Do not refactor unrelated files.

ACCEPTANCE CHECKS
- Code builds.
- Existing tests pass (add tests only if the repo already uses them for handlers/services).
- Run gofmt on changed files.

FINAL INSTRUCTION
Before writing code, list any assumptions you must make. If an assumption is risky, ask a short question instead.

Das wirkt, weil es drei Dinge erzwingt: einen Kontext‑Block (was existiert), einen Constraints‑Block (was nicht zu tun ist) und konkrete JSON‑Beispiele (damit Shapes nicht driften). Die letzte Anweisung ist dein Sicherheitsnetz: Wenn das Modell unsicher ist, soll es vor dem Schreiben fragen.

Realistisches Beispiel: Create‑Endpoint hinzufügen ohne Stil zu brechen

Ship and test faster
Host your API after scaffolding so you can test real client behavior early.
Deploy App

Angenommen, du willst einen „Create project“ Endpoint hinzufügen. Ziel: einen Namen akzeptieren, ein paar Regeln durchsetzen, speichern und eine neue ID zurückgeben. Knifflig ist, denselben Handler‑Service‑Repo‑Split und dieselbe Error‑JSON beizubehalten.

Ein konsistenter Ablauf sieht so aus:

  • Handler: JSON binden, einfache Feldvalidierung, Service aufrufen
  • Service: Geschäftsregeln anwenden (z. B. Eindeutigkeit), Repo aufrufen, Domain‑Resultat zurückgeben
  • Repo: In Postgres schreiben, generierte ID zurückgeben

Hier die Anfrage, die der Handler akzeptiert:

{ "name": "Roadmap", "owner_id": "u_123" }

Bei Erfolg: 201 Created zurückgeben. Die ID sollte immer aus derselben Quelle kommen. Zum Beispiel Postgres sie generieren lassen und vom Repo zurückgeben:

{ "id": "p_456", "name": "Roadmap", "owner_id": "u_123", "created_at": "2026-01-09T12:34:56Z" }

Zwei realistische Fehlerpfade:

Wenn die Validierung fehlschlägt (fehlender oder zu kurzer Name), gib einen Feldfehler in deiner Standardform und mit dem gewählten Statuscode zurück:

{ "error": { "code": "VALIDATION_ERROR", "message": "Invalid request", "details": { "name": "must be at least 3 characters" } } }

Wenn der Name pro Owner eindeutig sein muss und der Service ein bestehendes Projekt findet, gib 409 Conflict zurück:

{ "error": { "code": "PROJECT_NAME_TAKEN", "message": "Project name already exists", "details": { "name": "Roadmap" } } }

Eine Entscheidung, die das Muster sauber hält: Der Handler prüft „ist die Anfrage korrekt geformt?“, während der Service prüft „ist das erlaubt?“. Diese Trennung macht generierte Endpunkte vorhersehbar.

Häufige Fehler, die Konsistenz zerstören (und wie du sie vermeidest)

Der schnellste Weg, Konsistenz zu verlieren, ist, dem Generator zu erlauben, zu improvisieren.

Ein häufiger Drift ist eine neue Fehler‑Form. Ein Endpoint gibt {error: "..."} zurück, ein anderer {message: "..."}, ein dritter fügt ein verschachteltes Objekt hinzu. Behebe das, indem du eine einzige Fehler‑Hülle und eine Statuscode‑Map an einem Ort hältst und neue Endpunkte zwingst, diese per Importpfad und Funktionsnamen wiederzuverwenden. Wenn der Generator ein neues Feld vorschlägt, behandle das wie eine API‑Änderung, nicht als Bequemlichkeit.

Handler‑Bloat ist ein weiterer Drift. Es startet klein: validieren, dann Permissions prüfen, dann DB abfragen, dann auf Business‑Regeln verzweigen. Bald sieht jeder Handler anders aus. Eine Regel: Handler übersetzen HTTP in typisierte Inputs/Outputs; Services übernehmen Entscheidungen; Data Access übernimmt Queries.

Namensmismatch addiert sich ebenfalls. Wenn ein Endpoint CreateUserRequest verwendet und ein anderer NewUserPayload, verschwendest du Zeit beim Suchen und Schreibkonnektoren. Wähle ein Namensschema und lehne neue Namen ab, außer es gibt einen guten Grund.

Gib niemals rohe Datenbankfehler an Clients zurück. Abgesehen davon, dass du Details leakst, erzeugt es inkonsistente Nachrichten und Statuscodes. Wrappe interne Fehler, logge die Ursache und gib einen stabilen öffentlichen Fehlercode zurück.

Vermeide es, neue Bibliotheken „nur aus Bequemlichkeit“ hinzuzufügen. Jeder zusätzliche Validator, Router‑Helper oder Error‑Paket wird zu einem weiteren Stil, den es abzustimmen gilt.

Guardrails, die die meisten Probleme verhindern:

  • Fordere neue Endpunkte auf, bestehende Fehlertypen und Helfer wiederzuverwenden.
  • Halte Handler frei von Business‑Regeln und DB‑Zugriff.
  • Erzwinge eine Namenskonvention für Request‑ und Response‑Structs.
  • Mappe interne Fehler auf öffentliche Fehlercodes, niemals rohe Fehler.
  • Füge Dependencies nur mit schriftlicher Begründung hinzu.

Wenn du zwei Endpunkte nicht diffen kannst und dieselbe Form (Imports, Flow, Error‑Handling) erkennst, verschärfe den Prompt und regeneriere, bevor du merge.

Schnell‑Checkliste vor dem Merge eines generierten Endpunkts

Add safe rollback points
Capture a known-good state before bigger refactors or batch-generated endpoints.
Take Snapshot

Bevor du etwas generiertes mergest, prüfe zuerst die Struktur. Wenn die Form stimmt, sind Logikbugs leichter zu finden.

Structure‑Checks:

  • Handler‑Flow konsistent: Input binden, validieren, Service aufrufen, Domain‑Fehler auf HTTP mappen, Response schreiben.
  • Service‑Code enthält nur Geschäftsregeln: kein direktes HTTP oder JSON.
  • Erfolgsantworten entsprechen deinem Hausstil (entweder gemeinsame Hülle überall oder direktes JSON überall).
  • Fehlerantworten einheitlich: gleiche JSON‑Felder, gleiche Codes, gleiches request_id‑Verhalten.
  • Namensgebung und Ablage sind langweilig: Dateinamen, Funktionsnamen und Routen entsprechen bestehenden Endpunkten, alles gofmt‑formatiert.

Behavior‑Checks:

  • Tests ausführen und mindestens einen kleinen Test für einen neuen Handler/Service‑Zweig hinzufügen.
  • Bestätigen, dass Validierungsfehler denselben Code/Status wie ähnliche Endpunkte zurückgeben.
  • Einen bekannten Service‑Fehler (z. B. not found oder conflict) auslösen und Status/JSON‑Shape prüfen.
  • Auf Copy‑Paste‑Reste prüfen: falscher Routenpfad, falsche Log‑Nachricht, nicht übereinstimmende DTO‑Namen.
  • Den Server lokal bauen und starten, um Wiring und Imports zu prüfen.

Nächste Schritte: Muster standardisieren, dann sichere Skalierung der Generierung

Behandle dein Muster als gemeinsamen Vertrag, nicht als Vorliebe. Halte das „wie wir Endpunkte bauen“‑Dokument neben dem Code und pflege einen Referenz‑Endpoint, der den kompletten Ansatz end‑to‑end zeigt.

Skaliere die Generierung in kleinen Chargen. Generiere 2–3 Endpunkte, die verschiedene Ecken abdecken (ein einfacher Read, ein Create mit Validierung, ein Update mit Not‑Found‑Fall). Dann stoppe und verfeinere. Wenn Reviews immer dieselben Stil‑Drifts finden, aktualisiere das Baseline‑Dok und den Referenz‑Endpoint bevor du mehr generierst.

Eine wiederholbare Schleife:

  • Schreibe die Basis nieder: Dateinamen, Funktionsnamen, Request/Response‑Structs, Fehlercodes und wo Validierung passiert.
  • Halte einen Endpoint „golden“ und aktualisiere ihn zuerst, wenn sich das Muster ändert.
  • Batch‑generiere ein paar Endpunkte, reviewe auf Konsistenz und passe Prompt und Pattern‑Dok an.
  • Refaktoriere ältere Endpunkte in Blöcken und halte einen Rollback‑Pfad, falls sich Verhalten ändert.
  • Messe eine Kennzahl für eine Woche: Zeit bis zur Fertigstellung eines Endpunkts, Bug‑Rate nach Merge oder Review‑Zeit.

Wenn du einen strengeren Build‑Review‑Loop willst, kann eine Vibe‑Coding‑Plattform wie Koder.ai (koder.ai) helfen, Scaffoldings und Iterationen schnell in einem Chat‑getriebenen Workflow zu machen und den Source zu exportieren, sobald er deinem Standard entspricht. Das Tool ist weniger entscheidend als die Regel: Die Baseline bleibt das Kommando.

FAQ

What’s the fastest way to stop a Go API from getting inconsistent?

Locke ein wiederholbares Template früh fest: eine konsistente Schichtung (Handler → Service → Data Access), eine einheitliche Fehler-Hülle und eine Zuordnung von Statuscodes. Verwende dann einen einzelnen „Reference Endpoint“ als Beispiel, dem jeder neue Endpoint folgen muss.

What should a handler do (and not do)?

Halte Handler HTTP-only:

  • Binde/parsiere die Anfrage
  • Mache grundlegende „Shape-Validierung“ (erforderliche Felder, einfache Formate)
  • Rufe den Service auf
  • Mappe typisierte Fehler auf HTTP-Statuscodes
  • Schreibe JSON mit gemeinsamen Hilfsfunktionen

Wenn du SQL, Berechtigungsprüfungen oder Business-Logik in einem Handler siehst, verschiebe das in den Service.

What belongs in the service layer?

Platziere Geschäftsregeln und Entscheidungen im Service:

  • Berechtigungen und Zugriffsregeln
  • Invarianten (Zustandsübergänge, Eindeutigkeitsregeln, „erlaubt“-Prüfungen)
  • Orchestrierung über Repositories und externe Aufrufe

Der Service sollte Domain-Ergebnisse und typisierte Fehler zurückgeben—keine HTTP-Statuscodes, kein JSON-Shaping.

What belongs in the data access/repository layer?

Isoliere Persistenz‑Belange:

  • SQL/Queries und Transaktionen
  • Mapping von Rows zu Structs
  • Rückgabe von Storage‑Fehlern (die der Service interpretieren kann)

Vermeide, API-Antwortformate zu kodieren oder Business‑Regeln im Repo durchzusetzen (außer grundlegende Datenintegrität).

Where should validation live?

Eine einfache Standard‑Aufteilung:

  • Handler validiert die Request-Form (fehlende Felder, Basisformat)
  • Services validieren die Bedeutung (Berechtigungen, Invarianten, Zustand)

Beispiel: Der Handler prüft, dass email vorhanden ist und wie eine E‑Mail aussieht; der Service prüft, ob sie erlaubt ist und noch nicht verwendet wird.

What should a standard API error response look like?

Verwende überall dieselbe Fehler‑Hülle und halte sie stabil. Eine praktikable Form ist:

  • code für Maschinen (stabil)
  • message für Menschen (kurz und sicher)
  • details für strukturierte Extras (wie Feldfehler)
  • request_id zur Nachverfolgung

Das vermeidet spezielle Fälle auf Client‑Seite und macht generierte Endpunkte vorhersehbar.

How do I choose between 400 vs 422 vs 409 for errors?

Schreibe eine Statuscode‑Map fest und halte dich daran. Eine übliche Aufteilung:

Should I ever return raw database errors to clients?

Gebe sichere, konsistente öffentliche Fehler zurück und logge die echte Ursache intern.

  • Response: stabiler code, kurze message, plus request_id
  • Logs: volle Fehlerdetails (SQL‑Fehler, Upstream‑Payloads, User‑IDs)

So vermeidest du Informationsleaks und inkonsistente Fehlermeldungen über Endpunkte hinweg.

What is a reference endpoint, and why do I need one?

Erstelle einen „golden“ Reference Endpoint, dem neue Endpunkte entsprechen müssen:

  • Gleicher Flow (bind → validate → service → error map → JSON)
  • Gleiche Helfer (BindJSON, WriteJSON, WriteError usw.)
  • Gleiche Ordnerstruktur und Namenskonventionen

Füge ein paar kleine Tests hinzu (z. B. Table‑Tests für Error‑Mapping), um das Muster zu verankern.

How do I prompt Claude to generate new endpoints without breaking my structure?

Gib dem Modell strengen Kontext und klare Einschränkungen:

  • Füge den Reference Endpoint und die Pattern‑Regeln ein
  • Gib Route, Request/Response‑JSON‑Beispiele und Fehlerfälle an
  • Liste genau welche Dateien ausgegeben werden dürfen
  • Sag explizit, was nicht geändert werden darf (Router, Error‑Format, Helfer)

Nach der Generierung: lehne Diffs ab, die die Architektur „verbessern“ statt dem Baseline‑Muster zu folgen.

Inhalt
Warum Go-APIs chaotisch werden, wenn Muster nicht früh festgelegt werdenWähle eine Schichtaufteilung: Handler, Service und Data AccessDefiniere eine standardisierte Fehler‑Antwort und Statuscode‑MapOrdnerstruktur und Namensgebung, die Generierung vorhersehbar machtErstelle einen Referenz‑Endpoint, der das Muster setztSchritt für Schritt: Claude einen neuen Endpoint passend erzeugen lassenEine wiederverwendbare Prompt‑Vorlage für konsistente Endpoint‑ScaffoldsRealistisches Beispiel: Create‑Endpoint hinzufügen ohne Stil zu brechenHäufige Fehler, die Konsistenz zerstören (und wie du sie vermeidest)Schnell‑Checkliste vor dem Merge eines generierten EndpunktsNächste Schritte: Muster standardisieren, dann sichere Skalierung der GenerierungFAQ
Teilen
Koder.ai
Erstellen Sie Ihre eigene App mit Koder heute!

Der beste Weg, die Leistungsfähigkeit von Koder zu verstehen, ist es selbst zu erleben.

Kostenlos startenDemo buchen
  • 400 für fehlerhaftes JSON (bad_json)
  • 422 für Validierungsfehler (validation_failed)
  • 404 für nicht gefundene Ressourcen (not_found)
  • 409 für Konflikte (Duplikate/Version‑Mismatch)
  • 500 für unerwartete Fehler
  • Wichtig ist Konsistenz: keine Einzelfall‑Debatten pro Endpoint.