Skip to content

About

A Go REST API built contract first, with oapi-codegen for the server and sqlc for the queries

Topics

Resources

Code of conduct

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

Go OpenAPI and sqlc Example

A Go REST API built contract first. The OpenAPI spec generates the server interface and a client, and the SQL queries generate the database code. You write only the handlers and the repository that connect the two.

What it shows

Two generators remove most of the hand-written code in a CRUD API:

Generator Reads Writes
oapi-codegen api/openapi.yml internal/gen/oapi/: the models and a strict Fiber server interface. pkg/gen/: a typed client
sqlc db/migrations/ and db/queries/users.sql internal/gen/db/: typed Go functions for each query, on pgx

The strict server interface has one method for each operation, with typed request and response objects. A handler cannot return a response that the spec does not declare: the compiler rejects it.

The generated code is not committed. mise run generate writes it, and mise run setup and mise run ci call it.

Run it

  1. Install mise and Docker.

  2. Install the tools, generate the code, and start Postgres:

    git clone git@github.com:tabmadi/go-oapi-sqlc-example.git
    cd go-oapi-sqlc-example
    mise install
    mise run setup
    cp .env.example .env
    mise run db:up
    mise run migrate
  3. Start the API, then call it:

    mise run serve
    curl -s -XPOST localhost:8080/users -H 'Content-Type: application/json' -d '{"name":"Ada","email":"ada@example.com"}'
    curl -s 'localhost:8080/users?limit=10'

Endpoints

Method Path Does
GET /users Lists users. name and email filter, and limit and offset page
POST /users Creates a user
GET /users/{id} Gets one user
PUT /users/{id} Updates a user
DELETE /users/{id} Deletes a user

api/openapi.yml is the full contract.

Configuration

Variable Description Default
DATABASE_URL The Postgres connection string. It is required none
LISTEN_ADDRESS The address the server binds localhost:8080
READ_TIMEOUT The request read timeout 15s
WRITE_TIMEOUT The response write timeout 15s
IDLE_TIMEOUT The keep-alive idle timeout 60s
SHUTDOWN_TIMEOUT The time a shutdown waits for open requests 5s

How it works

File Holds
api/openapi.yml The contract: paths, parameters, and schemas
db/migrations/ The schema, applied by golang-migrate. sqlc reads it too
db/queries/users.sql The queries, with sqlc annotations
configs/ The generator, linter, and SQL formatter configs
internal/repository/ Maps between the API models and the database rows
internal/server/server.go The handlers that implement the strict server interface
internal/config/config.go Reads the configuration from the environment and .env
cmd/api/main.go Wires the parts and starts the server

What is deliberately missing

  • Tests: the example has none. The generated interface makes the handlers easy to test with a fake repository.
  • Safe error messages: a 500 response carries the database error text. A production API logs the error and returns a generic message.
  • Validation from the spec: the server does not check requests against the OpenAPI schema. A request validator middleware adds it.
  • Auth, rate limits, and structured logs.

Tasks

Task Does
mise run setup Downloads the modules, generates the code, and installs the git hooks
mise run generate Generates the server, the client, and the queries
mise run db:up Starts the local Postgres. db:down stops it and deletes its data
mise run migrate Applies the migrations
mise run serve Runs the API from source
mise run build Builds a static binary at bin/api
mise run lint Runs lint:go, lint:sql, lint:md, and lint:secrets
mise run format Applies every formatter
mise run check Runs lint and test. Run it before you finish a change
mise run ci Runs exactly what CI runs. The pre-push hook runs it too

License

Apache License 2.0. See LICENSE.

About

A Go REST API built contract first, with oapi-codegen for the server and sqlc for the queries

Topics

Resources

Code of conduct

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Contributors

Languages

Generated from tabmadi/go-template