Welcome! This project is a practical demonstration of a minimal Go REST API for user management. It showcases best practices in:
- JSON handling with Go structs
- Clean and modular code organization
- Input validation
- PostgreSQL integration
- Standardized error responses
This demo has been created for a talk at the First Online Go Language Conference for the South African Community.
Slides for this talk(slides.md) were prepared using Marp for Markdown-based presentations.
This diagram illustrates the HTTP handler flow in Go:
- HTTP Request – A request is received by the server (e.g.
POST /users). - Router – The request is routed using a multiplexer.
- Handler Function – The request is handled by a function.
- Decode JSON – The handler decodes the request body into a Go struct using
json.NewDecoder(r.Body).Decode(&input). - Create or Prepare Struct – The handler may directly use the input or prepare a new response struct.
- Returns struct/data – A struct is prepared for response.
- Encode JSON Response – The struct is encoded to JSON using
json.NewEncoder(w).Encode(user). - HTTP JSON Response Sent – JSON is sent back to the client as the response.
📌 The above can be adapted and extended by service or business logic.—.
- CRUD for users (Create, Read, Update, Delete)
- PostgreSQL storage
- Clean project structure, easy to extend
- Input validation for safer data
- Consistent, clear error handling
Requirements:
- Go 1.24 +
- PostgreSQL (local or remote)
Get Started:
git clone https://github.com/EmAchieng/struct-to-json.gitCreate a PostgreSQL database and user for this app.
-
Create your database and user (in psql or DBeaver, etc):
CREATE DATABASE structs_demo; CREATE USER demo_user WITH PASSWORD '$DB_PASSWORD'; -- Password stored securely elsewhere GRANT ALL PRIVILEGES ON DATABASE structs_demo TO demo_user;
-
Run the migration to set up the
userstable:CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, username VARCHAR(64) NOT NULL UNIQUE, email VARCHAR(128) NOT NULL UNIQUE, active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT NOW() );
Set the DATABASE_URL environment variable for your connection.
Example for your terminal:
export DATABASE_URL="postgres://demo_user:$DB_PASSWORD@localhost:5432/structs_demo?sslmode=disable"If your database is external, use the external host or IP:
DATABASE_URL=postgres://demo_user:yourpassword@<EXTERNAL_HOST>:5432/structs_demo?sslmode=disable
Replace <EXTERNAL_HOST> with your external database server’s address (e.g., db.example.com or an IP).
Make sure your firewall and database settings allow remote connections.
Install dependencies and start the server:
go mod tidy
go run cmd/server/main.goThe server will listen on http://localhost:8080.
Install dependencies and start the server:
docker build -t structs-to-json .docker run --rm -p 8080:8080 \
-e DATABASE_URL="postgres://demo_user:${DB_PASSWORD}@host.docker.internal:5432/structs_demo?sslmode=disable" \
structs-to-json| Method | Path | Description |
|---|---|---|
| GET | /users |
List all users |
| POST | /users |
Create a user |
| GET | /users/{id} |
Get user by ID |
| PUT | /users/{id} |
Update user by ID |
| DELETE | /users/{id} |
Delete user by ID |
| GET | /healthz |
Health check |
Create:
curl -X POST -H "Content-Type: application/json" \
-d '{"username":"gopher","email":"gopher@example.com","active":true}' \
http://localhost:8080/usersList:
curl http://localhost:8080/users- Production Tip: Always use HTTPS for API requests in production.
-
Want to use a different database? Implement the
UserStoreinterface for your backend. -
Add authentication, logging, or more resource types as needed.
-
Integrate with a frontend or deploy as a microservice.
-
Structs are powerful, but interfaces let us abstract behavior and write code that’s easier to test and extend. By combining structs and interfaces, we get the best of both worlds in Go API design.
-
Maintenance Tip: Regularly update dependencies to receive security patches.
-
Extend API endpoints to support pagination, filtering, or advanced queries.
MIT License — see LICENSE for details.
