A small Go HTTP API for creating and fetching student records using SQLite. It demonstrates:
- Config management via YAML or environment variables using cleanenv
- Go 1.22+
http.ServeMux
pattern-based routing - Storage abstraction via an interface with a SQLite implementation
- Simple request validation and JSON responses
- Go 1.22+
- net/http with pattern routes (Go 1.22)
- SQLite (github.com/mattn/go-sqlite3)
- Config: github.com/ilyakaznacheev/cleanenv
- Validation: github.com/go-playground/validator/v10
.
├─ cmd/students-api/main.go # App entrypoint
├─ config/local.yaml # Example config (ignored by git)
├─ internal/
│ ├─ config/config.go # MustLoad() config loader
│ ├─ http/handlers/student/*.go # HTTP handlers
│ ├─ storage/
│ │ ├─ storage.go # Storage interface
│ │ └─ sqlite/sqlite.go # SQLite implementation and schema init
│ ├─ types/types.go # DTOs (Student)
│ └─ utils/response/response.go # JSON response helpers
└─ storage/storage.db # SQLite database file
Config is loaded by config.MustLoad()
from either:
CONFIG_PATH
environment variable, or-config
CLI flag.
If neither is provided, the app will exit with: "Config path not set".
Sample config/local.yaml
:
env: "dev"
storage_path: "storage/storage.db"
http_server:
address: "localhost:8800"
Config struct mapping (internal/config/config.go
):
env
->Config.Env
(alsoENV
env var, required)storage_path
->Config.StoragePath
(required)http_server.address
->Config.HTTPServer.Addr
Note: .gitignore
excludes /config
and /storage
by default, so example files may not be in a fresh clone.
From project root:
# Ensure deps are tidy
go mod tidy
# Run with config path
go run ./cmd/students-api -config config/local.yaml
The server listens on the address from config (http_server.address
).
Base URL: http://localhost:8800
-
POST
/api/students
— create a student- Request JSON:
{ "name": string, "email": string, "age": number }
- Response 201:
{ "id": number }
- Request JSON:
-
GET
/api/students/{id}
— get a student by id- Response 200:
{ "id": number, "name": string, "email": string, "age": number }
- Response 200:
-
GET
/api/students
— list all students- Response 200:
[{...}, {...}]
- Response 200:
# Create
curl -i -X POST http://localhost:8800/api/students \
-H 'Content-Type: application/json' \
-d '{"name":"Ada","email":"[email protected]","age":20}'
# Get by id
curl -i http://localhost:8800/api/students/1
# List
curl -i http://localhost:8800/api/students
- Router: uses Go 1.22
http.NewServeMux()
with pattern handlers:POST /api/students
GET /api/students/{id}
GET /api/students
- Handlers use
response.WriteJson
for consistent JSON responses. - Validation with
validator.v10
; missing required fields return a readable error message. - SQLite schema is created automatically on startup if not present.
- If developing in WSL and inspecting the DB from Windows tools (e.g., TablePlus), copy the DB file to a Windows path (
/mnt/c/...
) or use a VS Code SQLite extension inside WSL. - VS Code: install "SQLite Viewer/Explorer" extension and open
storage/storage.db
directly.
- 404 on routes:
- Ensure exact paths:
/api/students
vs/api/students/
(ServeMux treats them differently). Optionally register both.
- Ensure exact paths:
- Config not found:
- Provide
-config config/local.yaml
or setCONFIG_PATH
.
- Provide
- Import path errors:
- Ensure
module
ingo.mod
matches your imports (e.g.,github.com/observer04/students-api
). Run from project root.
- Ensure
- Go version and routing:
- Requires Go 1.22+ for pattern routes and
r.PathValue("id")
.
- Requires Go 1.22+ for pattern routes and
- SQLite compile error (missing return):
- Ensure all code paths in functions return the proper values.
- WSL path issues:
- Windows apps can’t directly open WSL paths reliably; copy DB to
/mnt/c/...
or use WSL-side tools.
- Windows apps can’t directly open WSL paths reliably; copy DB to
MIT (or your preferred license)