Simplifica la lógica de backend con generación de código en Go

Simplifica la lógica de backend con generación de código en Go

El desarrollo de backend se llena de código repetitivo, sobre todo alrededor de las consultas a la base de datos y de los servidores de API. Escribir ese código a mano es lento y fácil de romper. Las herramientas de generación de código (codegen) convierten una especificación declarativa en código Go con tipos, sin que tengas que mantenerlo a mano.

En este artículo verás dos herramientas:

¿Por qué usar generación de código?

Generación de SQL con sqlc

¿Qué es sqlc?

sqlc lee tus archivos .sql y genera funciones Go que ejecutan esas consultas con parámetros y resultados tipados.

Cómo usar sqlc

  1. Escribe el esquema y las consultas.
  2. Define la entrada y la salida en sqlc.yaml.
  3. Ejecuta sqlc generate.

Ejemplo

Supón que tienes una tabla users:

-- schema.sql
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    email TEXT UNIQUE NOT NULL
);

Y una consulta que busca un usuario por correo:

-- queries.sql
-- name: GetUserByEmail :one
SELECT id, name, email FROM users WHERE email = $1;

La configuración de sqlc.yaml:

version: "1"
packages:
  - name: "db"
    path: "./db"
    queries: "./queries.sql"
    schema: "./schema.sql"
    engine: "postgresql"

Ejecuta:

sqlc generate

sqlc genera un método como este:

func (q *Queries) GetUserByEmail(ctx context.Context, email string) (User, error)

Úsalo en el backend:

user, err := dbQueries.GetUserByEmail(ctx, "alice@example.com")
if err != nil {
    // handle error
}
fmt.Println("User:", user.Name)

El manejo manual del string SQL y el escaneo de filas desaparecen. El código queda más limpio y más seguro.

Generación del servidor con oapi-codegen

¿Qué es oapi-codegen?

oapi-codegen lee una especificación OpenAPI y genera código de servidor y de cliente en Go. Crea las interfaces y los tipos de petición y respuesta. Solo te queda implementar la lógica de negocio.

Cómo usar oapi-codegen

  1. Define la API en un archivo OpenAPI YAML o JSON.
  2. Ejecuta oapi-codegen.
  3. Implementa los métodos de la interfaz generada.

Ejemplo

Esta es una especificación OpenAPI pequeña, api.yaml:

openapi: 3.0.0
info:
  title: User API
  version: 1.0.0
paths:
  /users/{email}:
    get:
      summary: Get user by email
      parameters:
        - name: email
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: User found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"
        "404":
          description: User not found
components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        email:
          type: string

Genera el código del servidor:

oapi-codegen -generate types,server -package api -o api.gen.go api.yaml

Esto produce los tipos de petición y respuesta, como el struct User, además de una interfaz ServerInterface con un método:

GetUsersEmail(ctx context.Context, email string) (api.User, error)

Implementa la interfaz:

type ServerImpl struct {
    db *db.Queries
}
 
func (s *ServerImpl) GetUsersEmail(ctx context.Context, email string) (api.User, error) {
    user, err := s.db.GetUserByEmail(ctx, email)
    if err != nil {
        return api.User{}, err
    }
    return api.User{
        Id:    int64(user.ID),
        Name:  user.Name,
        Email: user.Email,
    }, nil
}

Conecta el servidor:

router := api.NewRouter(&ServerImpl{db: dbQueries})
http.ListenAndServe(":8080", router)

Beneficios de combinar sqlc y oapi-codegen

Conclusión

sqlc y oapi-codegen juntos automatizan el acceso a la base de datos y el código del servidor de API en un backend de Go. Escribes menos código repetitivo y te encuentras con menos errores en ejecución. El foco se queda donde corresponde, en la lógica central de la aplicación.

© Melvin Laplanche - All rights reserved.