A Go REST API for a mango shop. Supports user auth (JWT), mango inventory management, and order placement. Uses Echo v5, GORM, and PostgreSQL (Neon).
- Prerequisites
- Step 1 — Install Go
- Step 2 — Set Up PostgreSQL (Neon)
- Step 3 — Clone / Create Project
- Step 4 — Initialize Go Module
- Step 5 — Install Dependencies
- Step 6 — Configure Environment
- Step 7 — Install Air (Hot Reload)
- Step 8 — Run the Project
- Project Structure
- API Endpoints
- How Each Package Works
| Tool | Version | Purpose |
|---|---|---|
| Go | 1.21+ | Language runtime |
| Git | Any | Version control |
| PostgreSQL | Any (or Neon cloud) | Database |
| Air | Latest | Hot reload (optional) |
- Download from https://go.dev/dl/
- Run the installer
- Verify:
go version
# go version go1.25.0 windows/amd64- Make sure
GOPATHandGOBINare in your PATH. Usually auto-set by the installer.
go env GOPATH
go env GOBINThis project uses Neon — a free serverless PostgreSQL. You can also use a local PostgreSQL instance.
- Go to https://neon.tech and sign up
- Create a new project (e.g.
mangoshop) - Go to Dashboard → Connection Details
- Copy the connection string. It looks like:
postgresql://user:password@ep-xxx.region.aws.neon.tech/dbname?sslmode=require - Paste it into your
.envfile asDSN=...(see Step 6)
- Install PostgreSQL from https://www.postgresql.org/download/
- Create a database:
psql -U postgres
CREATE DATABASE mangoshop;
\q- Your DSN will be:
DSN="postgresql://postgres:yourpassword@localhost:5432/mangoshop?sslmode=disable"
Note: GORM auto-migrates all tables on startup. You do not need to create tables manually.
If cloning an existing repo:
git clone <repo-url>
cd haddiBangaIf starting from scratch:
mkdir haddiBanga
cd haddiBangago mod init haddibangaThis creates go.mod. The module name haddibanga is used as the import prefix across all internal packages (e.g. haddibanga/internal/config).
Run these commands one by one. Each installs a specific package and adds it to go.mod and go.sum.
go get github.com/labstack/echo/v5Echo is the web framework. It handles routing, middleware, and JSON binding.
go get gorm.io/gormGORM is the ORM used to define models and interact with the database. It auto-migrates structs to DB tables.
- Docs: https://gorm.io/docs/
go get gorm.io/driver/postgresThis is the Postgres adapter for GORM. Always install this alongside gorm.io/gorm when using PostgreSQL.
go get github.com/golang-jwt/jwt/v5Used to generate and validate access + refresh tokens.
go get github.com/go-playground/validator/v10Used to validate request DTOs using struct tags like validate:"required,email".
go get github.com/joho/godotenvLoads .env file into os.Getenv() at runtime.
go get golang.org/x/cryptoUsed to hash and compare user passwords with bcrypt.
go get github.com/google/uuidUsed to generate unique order codes.
go mod tidyThis downloads all missing packages and removes unused ones.
Create a .env file in the project root:
# .env
DSN="postgresql://user:password@host/dbname?sslmode=require"
PORT=8080
JWT_SECRET=your_secret_key_here| Variable | Description |
|---|---|
DSN |
Full PostgreSQL connection string |
PORT |
Port the server listens on |
JWT_SECRET |
Secret used to sign JWT tokens — change this in production |
Warning: Never commit
.envto git. It is already in.gitignore.
Air watches your .go files and restarts the server on changes. Optional but recommended for development.
go install github.com/air-verse/air@latestVerify:
air -vIf air is not found, add Go's bin directory to PATH:
- Windows: Add
%USERPROFILE%\go\binto your system PATH - Linux/Mac: Add
$HOME/go/binto your~/.bashrcor~/.zshrc
The .air.toml config file is already in the project. It builds to ./tmp/main.exe and watches .go, .html, .tmpl files.
airgo run ./cmd/main.gogo build -o ./tmp/main.exe ./cmd/main.go
./tmp/main.exeDatabase connection successful
⇨ http server started on [::]:8080
curl http://localhost:8080/health
# {"status":"ok"}haddiBanga/
├── cmd/
│ └── main.go # Entry point
├── internal/
│ ├── config/
│ │ ├── config.go # Loads .env into Config struct
│ │ └── db.go # Opens GORM DB connection
│ ├── auth/
│ │ └── jwt.go # JWT service (generate + validate tokens)
│ ├── middlewares/
│ │ └── auth.go # JWT auth middleware for protected routes
│ ├── httpresponse/
│ │ └── error.go # Standard error response struct
│ ├── server/
│ │ └── http.go # Creates Echo, auto-migrates DB, registers routes
│ └── domain/
│ ├── user/ # User registration, login, refresh, /me
│ │ ├── entity.go # User model + bcrypt methods
│ │ ├── repository.go # DB queries
│ │ ├── service.go # Business logic
│ │ ├── handler.go # HTTP handlers
│ │ ├── register.go # Route registration
│ │ └── dto/ # Request/response structs
│ ├── mango/ # Mango inventory
│ │ ├── entity.go # Mango model
│ │ ├── repository.go
│ │ ├── service.go
│ │ ├── handler.go
│ │ ├── register.go
│ │ └── dto/
│ └── order/ # Order placement
│ ├── entity.go # Order model (pending/confirmed/cancelled)
│ ├── repository.go
│ ├── service.go
│ ├── handler.go
│ ├── register.go
│ └── dto/
├── .env # Environment variables (not in git)
├── .air.toml # Air hot reload config
├── go.mod # Module definition + dependency list
├── go.sum # Dependency checksums
└── mangoshop.postman_collection.json # Postman collection for testing
| Method | URL | Auth |
|---|---|---|
| GET | /health |
No |
| Method | URL | Auth | Description |
|---|---|---|---|
| POST | /api/v1/auth/register |
No | Create account |
| POST | /api/v1/auth/login |
No | Login, returns access + refresh token |
| POST | /api/v1/auth/refresh |
No | Get new access token using refresh token |
| GET | /api/v1/auth/me |
Yes | Get current user info |
| Method | URL | Auth | Description |
|---|---|---|---|
| GET | /api/v1/mangoes |
No | List all mangoes |
| GET | /api/v1/mangoes/:id |
No | Get mango by ID |
| POST | /api/v1/mangoes |
Yes | Create new mango |
| PATCH | /api/v1/mangoes/:id |
Yes | Update mango |
| Method | URL | Auth | Description |
|---|---|---|---|
| POST | /api/v1/orders |
Yes | Place an order |
| GET | /api/v1/orders/me |
Yes | Get my orders |
Auth = requires Authorization: Bearer <access_token> header.
Reads .env with godotenv and returns a Config struct. db.go opens a GORM connection using the DSN. Called once at startup in main.go.
JWTService interface with two implementations: GenerateAccessToken (15 min TTL) and GenerateRefreshToken (7 days TTL). Tokens are signed with HS256.
AuthMiddleware validates the Bearer token from the Authorization header and sets user_id, user_email, user_name in Echo's context for downstream handlers.
Creates the Echo instance, attaches the custom validator (wraps go-playground/validator), calls db.AutoMigrate (creates tables if they don't exist), then calls each domain's RegisterRoutes.
- Register: hashes password with bcrypt, stores user
- Login: compares password, returns access + refresh tokens
- Refresh: validates refresh token, issues new access token
- Me: reads user info from context (set by middleware)
CRUD for mango inventory. Create and Update require auth. Get routes are public.
Creates an order by looking up the mango, checking stock, calculating total price, decrementing stock, and generating a unique order code (UUID). All routes require auth.
Import mangoshop.postman_collection.json into Postman:
- Open Postman → Import → select the file
- Register a user first (
POST /api/v1/auth/register) - Login to get tokens (
POST /api/v1/auth/login) - Set the access token in the
Authorizationheader asBearer <token>for protected routes
| Error | Cause | Fix |
|---|---|---|
Error loading .env file |
.env file missing |
Create .env in project root |
failed to connect database |
Wrong DSN | Check DSN in .env |
air: command not found |
Go bin not in PATH | Add ~/go/bin to PATH |
port already in use |
Another process on port 8080 | Change PORT in .env or kill the process |