A hands-on tutorial project for learning sqlc — a tool that generates type-safe code from SQL queries.
This project demonstrates the fundamentals of using sqlc with Go and PostgreSQL:
- SQL-first approach: Define queries in SQL, generate Go code automatically
- Type-safe database access: No reflection, compile-time type checking
- Zero runtime overhead: Generated code uses direct database driver calls
- Transaction support: Built-in patterns for working with transactions
- Go 1.24+
- Docker and Docker Compose (for PostgreSQL)
- sqlc CLI (optional, for generating code from queries)
docker-compose up -dThe PostgreSQL database will be available at localhost:5432 with:
- User:
user - Password:
secret - Database:
app
docker-compose exec postgres psql -U user -d app -f schema.sqlOr use your favorite PostgreSQL client to run schema.sql.
If you modify query.sql or schema.sql:
sqlc generateThis generates code in the tutorial/ directory.
go run tutorial.goThe application will:
- Connect to PostgreSQL
- List all authors
- Create a new author "Brian Kernighan"
- Fetch the created author by ID
- Verify the inserted and fetched data are identical
.
├── schema.sql # Database schema definition
├── query.sql # SQL queries with sqlc annotations
├── sqlc.yaml # sqlc configuration
├── tutorial.go # Application entry point
├── tutorial/ # Generated code (do not edit)
│ ├── db.go # Database interface and initialization
│ ├── models.go # Generated models
│ └── query.sql.go # Generated query methods
├── docker-compose.yml # PostgreSQL service configuration
├── go.mod # Go module definition
└── go.sum # Go module checksums
sqlc uses special comments to generate appropriate Go functions. See query.sql:
:one— Query returns exactly one row:many— Query returns zero or more rows:exec— Query is executed for side effects only
Example:
-- name: GetAuthor :one
SELECT * FROM authors WHERE id = $1 LIMIT 1;Generates a function: GetAuthor(ctx context.Context, id int64) (Author, error)
The tutorial/ directory contains auto-generated code:
- db.go: The
Queriesstruct that holds all database methods - models.go: Go struct definitions matching your SQL tables
- query.sql.go: Implementation of all query methods
Never edit generated files directly — they'll be overwritten when you regenerate.
- pgx v5 — PostgreSQL driver for Go with native pgtype support
- PostgreSQL 18 — Database server
- sqlc Documentation
- sqlc Playground — Try sqlc online
- pgx Documentation
- sqlc GitHub Repository
- Edit
query.sqland add your SQL query with a sqlc annotation - Run
sqlc generateto create Go methods - Use the generated methods in your code
tx, err := conn.Begin(ctx)
if err != nil {
return err
}
defer tx.Rollback(ctx)
queries := tutorial.New(tx)
// Use queries as normal
// ...
return tx.Commit(ctx)Use pgtype.Text, pgtype.Int4, etc. for nullable columns:
author := tutorial.Author{
Name: "Jane Doe",
Bio: pgtype.Text{
String: "Software engineer",
Valid: true, // true if value is present
},
}MIT
This project is a learning resource. For production use, consider: