go-api-design
Über
Dieses Claude Skill bietet REST- und gRPC-API-Designmuster für Go-Dienste und behandelt HTTP-Handler, Middleware, Routing und API-Dokumentation. Nutzen Sie es beim Entwerfen von APIs, Implementieren von Middleware, Strukturieren von REST-Endpunkten oder Einrichten von gRPC-Diensten. Es enthält praktische Anleitungen zu Versionierung, Paginierung, Graceful Shutdown und OpenAPI-Dokumentation.
Schnellinstallation
Claude Code
Empfohlennpx skills add eduardo-sl/go-agent-skills -a claude-code/plugin add https://github.com/eduardo-sl/go-agent-skillsgit clone https://github.com/eduardo-sl/go-agent-skills.git ~/.claude/skills/go-api-designKopieren Sie diesen Befehl und fügen Sie ihn in Claude Code ein, um diese Fähigkeit zu installieren
Dokumentation
Go API Design
APIs are contracts. Once published, they're promises. Design them as if you'll maintain them for a decade — because you probably will.
1. HTTP Handler Structure
Use the standard http.Handler interface:
// ✅ Good — method on a struct with dependencies
type UserHandler struct {
store UserStore
logger *slog.Logger
}
func (h *UserHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
h.handleGet(w, r)
case http.MethodPost:
h.handleCreate(w, r)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
}
Handler function signature pattern:
// Handler methods return nothing — they write directly to ResponseWriter.
// Errors are handled inside the handler, not returned.
func (h *UserHandler) handleGet(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
id := chi.URLParam(r, "id") // or mux.Vars(r)["id"]
if id == "" {
h.respondError(w, http.StatusBadRequest, "missing user id")
return
}
user, err := h.store.GetByID(ctx, id)
if err != nil {
if errors.Is(err, ErrNotFound) {
h.respondError(w, http.StatusNotFound, "user not found")
return
}
h.logger.Error("get user", slog.Any("error", err))
h.respondError(w, http.StatusInternalServerError, "internal error")
return
}
h.respondJSON(w, http.StatusOK, user)
}
JSON response helpers:
func (h *UserHandler) respondJSON(w http.ResponseWriter, status int, data interface{}) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
if err := json.NewEncoder(w).Encode(data); err != nil {
h.logger.Error("encode response", slog.Any("error", err))
}
}
func (h *UserHandler) respondError(w http.ResponseWriter, status int, msg string) {
h.respondJSON(w, status, map[string]string{"error": msg})
}
2. Middleware Pattern
Middleware wraps handlers. Use the standard func(http.Handler) http.Handler signature:
func RequestID(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := r.Header.Get("X-Request-ID")
if id == "" {
id = uuid.New().String()
}
ctx := context.WithValue(r.Context(), requestIDKey, id)
w.Header().Set("X-Request-ID", id)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
func Recoverer(logger *slog.Logger) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if rec := recover(); rec != nil {
logger.Error("panic recovered",
slog.Any("panic", rec),
slog.String("stack", string(debug.Stack())),
)
http.Error(w, "internal server error", http.StatusInternalServerError)
}
}()
next.ServeHTTP(w, r)
})
}
}
Middleware ordering (outside → inside):
Recoverer → RequestID → Logger → Auth → RateLimit → Handler
Recover MUST be outermost. Auth before business logic. Logger captures timing.
3. Request Validation
Decode and validate in one step:
type CreateUserRequest struct {
Name string `json:"name" validate:"required,min=2,max=100"`
Email string `json:"email" validate:"required,email"`
}
func decodeAndValidate[T any](r *http.Request) (T, error) {
var req T
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
return req, fmt.Errorf("decode: %w", err)
}
if err := validate.Struct(req); err != nil {
return req, fmt.Errorf("validate: %w", err)
}
return req, nil
}
Limit request body size:
r.Body = http.MaxBytesReader(w, r.Body, 1<<20) // 1 MB
4. URL and Naming Conventions
GET /api/v1/users → list users
POST /api/v1/users → create user
GET /api/v1/users/{id} → get user
PUT /api/v1/users/{id} → replace user
PATCH /api/v1/users/{id} → partial update
DELETE /api/v1/users/{id} → delete user
GET /api/v1/users/{id}/orders → list user orders (nested resource)
Rules:
- Plural nouns for resources:
/users, not/user - Kebab-case for multi-word paths:
/order-items - camelCase for JSON fields:
"createdAt","firstName" - Version in URL path:
/api/v1/... - No verbs in URLs:
/users/search?q=alice, NOT/searchUsers
5. Pagination
type PageRequest struct {
Cursor string `json:"cursor"`
Limit int `json:"limit"`
}
type PageResponse[T any] struct {
Items []T `json:"items"`
NextCursor string `json:"next_cursor,omitempty"`
HasMore bool `json:"has_more"`
}
Prefer cursor-based pagination over offset/limit for large datasets. Offset pagination breaks under concurrent writes.
6. Graceful Shutdown
func main() {
srv := &http.Server{
Addr: ":8080",
Handler: router,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 120 * time.Second,
}
// Start server
go func() {
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
log.Fatalf("server error: %v", err)
}
}()
// Wait for interrupt
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
// Graceful shutdown with timeout
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Fatalf("shutdown error: %v", err)
}
log.Println("server stopped gracefully")
}
Programs should exit only in main(), preferably at most once.
7. Health Check Endpoints
// Liveness: is the process alive?
// GET /healthz → 200 OK
// Readiness: can the process serve traffic?
// GET /readyz → 200 OK or 503 Service Unavailable
func (h *HealthHandler) handleReady(w http.ResponseWriter, r *http.Request) {
if err := h.db.PingContext(r.Context()); err != nil {
h.respondError(w, http.StatusServiceUnavailable, "database unavailable")
return
}
h.respondJSON(w, http.StatusOK, map[string]string{"status": "ready"})
}
8. Error Response Format
Consistent error responses across the entire API:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "invalid request parameters",
"details": [
{"field": "email", "message": "must be a valid email"}
]
}
}
Map internal errors to HTTP status codes at the handler boundary. Internal errors should NEVER leak to clients.
GitHub Repository
Häufig gestellte Fragen
Was ist der Skill go-api-design?
go-api-design ist ein Claude Skill von eduardo-sl. Skills bündeln Anweisungen und Ressourcen, die Claude bei Bedarf lädt, um Aufgaben rund um go-api-design ohne zusätzliche Eingaben auszuführen.
Wie installiere ich go-api-design?
Verwende die Installationsbefehle auf dieser Seite: Füge go-api-design als Plugin zu Claude Code hinzu oder klone das Repository in dein Skills-Verzeichnis. Starte Claude danach neu, damit der Skill geladen wird.
Zu welcher Kategorie gehört go-api-design?
go-api-design gehört zur Kategorie Design.
Kann ich go-api-design kostenlos nutzen?
Ja. go-api-design ist auf AIMCP gelistet und kann kostenlos installiert werden.
Verwandte Skills
Verwenden Sie die Fähigkeit "executing-plans", wenn Sie einen vollständigen Implementierungsplan zur Ausführung in kontrollierten Batches mit Überprüfungspunkten vorliegen haben. Sie lädt den Plan und überprüft ihn kritisch, führt dann Aufgaben in kleinen Batches (standardmäßig 3 Aufgaben) aus und meldet den Fortschritt zwischen jedem Batch zur Überprüfung durch den Architekten. Dies gewährleistet eine systematische Implementierung mit integrierten Qualitätskontrollpunkten.
Diese Fähigkeit sendet einen Unteragenten für Code-Review, um Codeänderungen anhand der Anforderungen zu analysieren, bevor fortgefahren wird. Sie sollte nach dem Abschließen von Aufgaben, der Implementierung größerer Funktionen oder vor dem Zusammenführen in den Hauptzweig verwendet werden. Die Überprüfung hilft dabei, Probleme frühzeitig zu erkennen, indem die aktuelle Implementierung mit dem ursprünglichen Plan verglichen wird.
Diese Fähigkeit bietet Entwicklern eine umfassende Anleitung, um MCP-Server über HTTP-, stdio- oder SSE-Transports mit Claude Code zu verbinden. Sie behandelt Installation, Konfiguration, Authentifizierung und Sicherheit für die Integration externer Dienste wie GitHub, Notion und benutzerdefinierter APIs. Nutzen Sie sie beim Einrichten von MCP-Integrationen, bei der Konfiguration externer Tools oder bei der Arbeit mit Claude's Model Context Protocol.
Diese Fähigkeit unterstützt Entwickler bei der Wahl zwischen Claude Code Web- und CLI-Schnittstellen basierend auf Aufgabenanalysen und ermöglicht nahtloses Session-Teleporting zwischen diesen Umgebungen. Sie optimiert den Workflow, indem sie den Sitzungsstatus und Kontext beim Wechsel zwischen Web, CLI oder Mobilgeräten verwaltet. Nutzen Sie sie für komplexe Projekte, die in verschiedenen Phasen unterschiedliche Werkzeuge erfordern.
