SuperAPI AI Directory

golang-apis

Coding & development

View repository

Updated 10-15 20:31

About this skill

Golang APIs (Gin)

Clear and stable contracts beat ad hoc handlers. Every mutation goes through binding, validation, and authorization on the server.

Stack and scope

Ask Role
Gin Router, middleware, binding, context
encoding/json JSON request/response (or the project's lib)
context Cancellation and request values
validator Tags binding:"required,..." of Gin

For background concurrency, WebSocket, SQL, testing, ops, or i18n: golang-goroutines, golang-websocket, golang-sqlc, golang-unit-testing, golang-production, i18n-backend. Language: golang. HTTP contracts: api-design.

Recommended organization

cmd/api/main.go
internal/
  config/
  http/
    router.go
    middleware/
    handlers/
  domain/          # ou services/ por bounded context
  repository/
  • main just wiring: config, deps, r.Run.
  • Thin handlers; business logic in services.
  • Preserve the layout and libs already adopted by the project.

Non-negotiable rules

  • Handlers: func(c *gin.Context); never ignore c.Request.Context().
  • Bind with ShouldBindJSON / ShouldBindQuery / URI; fail with 400 typed.
  • Authn ≠ Authz: authenticated does not authorize ownership/role.
  • Do not expose internal structs with secrets; use response DTOs.
  • Stable errors: { "code", "message", "details?" } + correct HTTP status codes.
  • Config and secrets via env; no hardcoding.
  • Graceful shutdown with http.Server + signal (not just r.Run blind in production).

Router and groups

r := gin.New()
r.Use(gin.Recovery(), RequestID(), Logger())

v1 := r.Group("/api/v1")
{
    v1.GET("/health", health)

    auth := v1.Group("/")
    auth.Use(Authenticate())
    auth.GET("/todos", listTodos)
    auth.POST("/todos", createTodo)

    admin := v1.Group("/admin")
    admin.Use(Authenticate(), RequireRole("admin"))
    admin.GET("/users", listUsers)
}
  • Versioning (/api/v1) when the API is public or multi-client.
  • Auth middleware on the group, not copied into each route.
  • Typed path params; reject invalid IDs early.

Binding, validation, and errors

type CreateTodoRequest struct {
    Title string `json:"title" binding:"required,min=1,max=200"`
}

func createTodo(c *gin.Context) {
    var req CreateTodoRequest
    if err := c.ShouldBindJSON(&req); err != nil {
        c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
            "code": "validation_error", "message": "invalid request", "details": err.Error(),
        })
        return
    }
    // service call with c.Request.Context()
}
  • Status: 400, 401, 403, 404, 409, 422, 429, 500 as appropriate.
  • code machine-readable; message safe; no stack in production.
  • Distinguish validation (client) from internal failure (server).

Pagination and filters

  • Cursor-based for large lists; offset only when simple and limited.
  • Limit page size; reject abusive values.
  • Deterministic ordering.
  • Document supported filters.

Authorization

  • Extract identity in middleware; store it in c.Set with a typed/constant key.
  • Verify ownership/roles in the handler or service on every sensitive route.
  • Rate limit on auth and expensive endpoints when the risk exists.
  • Explicit CORS if there is a separate frontend.

Observability

  • Log request id, user id (if any), route, status, latency.
  • Do not log secrets or full sensitive payloads.
  • Propagate context.Context to the DB and HTTP clients.

Anti-patterns

  • Entire business logic in the handler
  • c.Get without checking existence / type
  • 200 with an error in the body without a convention
  • Ignore request cancellation
  • Validation only on the frontend
  • Gin in debug mode in production
  • Panic on the happy path instead of an HTTP error

Flow when implementing a feature

  1. Inspect existing router, middleware, and handlers.
  2. Define request/response DTO + validation rules.
  3. Service with the business rule (context-aware).
  4. Gin handler with authz and correct status codes.
  5. Tests for risk cases (golang-unit-testing).
  6. Update config/env/docs only for what changed.

Completion criteria

  • Routes grouped and versioned when applicable
  • Input validated; consistent errors and status codes
  • Authz covered on sensitive routes
  • Safe pagination/limits
  • Context propagated; no leakage of internal fields
  • Contract usable by at least one real client in the repo