A modern REST API built with Go, following clean architecture principles and best practices.
- Clean Architecture: Well-structured codebase with clear separation of concerns
- RESTful API: Complete CRUD operations for users
- Database Integration: PostgreSQL with GORM ORM
- Middleware Support: CORS, logging, and recovery middleware
- Environment Configuration: Flexible configuration management
- Docker Support: Containerized database setup
- Validation: Request validation using built-in Go validators
- Error Handling: Comprehensive error handling with meaningful responses
- Pagination: Built-in pagination support for list endpoints
This project follows the Clean Architecture pattern:
cmd/
├── main.go # Application entry point
internal/
├── config/ # Configuration management
├── domain/ # Business entities and models
├── handlers/ # HTTP handlers (controllers)
├── middleware/ # HTTP middleware
├── repository/ # Data access layer
└── service/ # Business logic layer
pkg/
└── database/ # Database connection and utilities
migrations/ # Database migrations
docker-compose.yml # Docker services
- Go 1.21 or higher
- Docker and Docker Compose
- PostgreSQL (or use Docker)
-
Clone the repository
git clone <repository-url> cd golang-backend
-
Install dependencies
go mod download
-
Start the database
docker-compose up -d
-
Copy environment file
cp .env.example .env
-
Run the application
go run cmd/main.go
The API will be available at http://localhost:8080
The application uses environment variables for configuration. Create a .env
file in the root directory:
# Database configuration
DB_HOST=localhost
DB_PORT=5432
DB_USER=user
DB_PASSWORD=password
DB_NAME=mydb
DB_SSL_MODE=disable
# Server configuration
SERVER_PORT=8080
ENV=development
GET /health
- Check API health status
POST /api/v1/users
- Create a new userGET /api/v1/users
- Get all users (with pagination)GET /api/v1/users/{id}
- Get user by IDPUT /api/v1/users/{id}
- Update userDELETE /api/v1/users/{id}
- Delete user
POST /api/v1/users
Content-Type: application/json
{
"name": "John Doe",
"email": "john@example.com"
}
Response:
{
"message": "User created successfully",
"data": {
"id": "uuid-here",
"name": "John Doe",
"email": "john@example.com",
"created_at": "2023-01-01T00:00:00Z",
"updated_at": "2023-01-01T00:00:00Z"
}
}
GET /api/v1/users?page=1&per_page=10
Response:
{
"data": [
{
"id": "uuid-here",
"name": "John Doe",
"email": "john@example.com",
"created_at": "2023-01-01T00:00:00Z",
"updated_at": "2023-01-01T00:00:00Z"
}
],
"total": 1,
"page": 1,
"per_page": 10,
"total_pages": 1
}
GET /api/v1/users/{id}
PUT /api/v1/users/{id}
Content-Type: application/json
{
"name": "Jane Doe",
"email": "jane@example.com"
}
DELETE /api/v1/users/{id}
-
Create a user:
curl -X POST http://localhost:8080/api/v1/users \ -H "Content-Type: application/json" \ -d '{"name": "John Doe", "email": "john@example.com"}'
-
Get all users:
curl http://localhost:8080/api/v1/users
-
Get user by ID:
curl http://localhost:8080/api/v1/users/{user-id}
-
Update user:
curl -X PUT http://localhost:8080/api/v1/users/{user-id} \ -H "Content-Type: application/json" \ -d '{"name": "Jane Doe"}'
-
Delete user:
curl -X DELETE http://localhost:8080/api/v1/users/{user-id}
docker-compose up -d
# Dockerfile example for containerizing the Go application
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o main cmd/main.go
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/main .
CMD ["./main"]
The API returns consistent error responses:
{
"error": "error_code",
"message": "Human-readable error message",
"details": "Additional error details (optional)"
}
Common error codes:
validation_error
- Invalid request datauser_not_found
- User doesn't existuser_exists
- User already exists (email conflict)internal_error
- Server error
- Clean Architecture: Separation of concerns with clear layers
- Dependency Injection: Loose coupling between components
- Interface-based Design: Repository and service interfaces
- Error Handling: Consistent error responses and proper error wrapping
- Validation: Input validation at handler level
- Configuration: Environment-based configuration
- Database: GORM with migrations and soft deletes
- Middleware: Reusable middleware for cross-cutting concerns
- UUID: Using UUIDs for primary keys for better security
- Pagination: Built-in pagination support
cmd/
: Application entry pointsinternal/
: Private application codeconfig/
: Configuration managementdomain/
: Business entities and DTOshandlers/
: HTTP request handlersmiddleware/
: HTTP middlewarerepository/
: Data access layer interfaces and implementationsservice/
: Business logic layer
pkg/
: Public library code that can be used by external applicationsmigrations/
: Database migration files
- Define the domain model in
internal/domain/
- Create repository interface and implementation in
internal/repository/
- Implement business logic in
internal/service/
- Create HTTP handlers in
internal/handlers/
- Add routes in
internal/handlers/routes.go
- Update database migrations if needed
This project is licensed under the MIT License - see the LICENSE file for details.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
If you have any questions or need help, please open an issue in the repository.
Happy Coding! 🎉