Home › Go › Go + Gin web API Windsurf rules
Go + Gin web API Windsurf rules
Windsurf rules for Go 1.27 REST APIs built with Gin: handlers, binding/validation, middleware, and tests.
WindsurfGo
How to use
Save this as .windsurf/rules/go-gin.md in your repository root, commit it, and your agent will pick it up automatically. Edit the commands to match your project.
.windsurf/rules/go-gin.mdDownload ---
trigger: glob
globs: **/*.go
---
# Go + Gin API
- Layout: `cmd/api/main.go` wires config, DB and router; `internal/<feature>/{handler.go,service.go,repo.go}`. `internal/` keeps packages private.
- `func NewRouter(svc *Services) *gin.Engine` builds routes so tests can call it with `httptest`.
- Bind and validate input with `c.ShouldBindJSON(&req)` and `binding:"required,email"` tags; on error return 400 with field messages. Never use `c.BindJSON` (it writes its own response).
- Handlers are thin: parse, call the service with `c.Request.Context()`, map errors to status codes in one helper.
- Middleware for request ID, structured logging (`slog`), recovery, auth, and CORS with explicit origins.
- Return consistent JSON errors: `{"error": {"code": "not_found", "message": "..."}}`.
- Database through `pgx`/`sqlc` or the repo's choice; always pass the context, parameterized queries only.
- Graceful shutdown: `http.Server` + `srv.Shutdown(ctx)` on SIGINT/SIGTERM instead of `r.Run()`.
- Set `gin.SetMode(gin.ReleaseMode)` from config in production.
## Don't
- Don't keep state in package-level variables, or start goroutines from handlers without a context.
## Done when
`go vet ./...`, `golangci-lint run`, and `go test -race ./...` pass, including a handler test for each new route.