Welcome to the Book Management API! A robust and scalable RESTful API built with Go, following SOLID principles and clean architecture patterns.
This API was designed to demonstrate modern Go development practices with a focus on maintainability, testability, and scalability. The project showcases:
- Clean Architecture - Separation of concerns with domain-driven design
- SOLID Principles - Following best practices for object-oriented design
- Comprehensive Testing - Unit tests with mocks for reliable code
- Error Handling - Custom error types for better error management
- Middleware Support - Logging and recovery middleware
- Type Safety - Leveraging Go's strong typing system
cmd/
api/
main.go # Entry point and DI container
internal/
domain/
book.go # Domain entity
repository.go # Repository interface
handler/
book_handler.go # HTTP handlers
middleware/
logger.go # Logging middleware
recovery.go # Panic recovery middleware
repository/
book_repository.go # In-memory implementation
service/
book_service.go # Business rules
Each component has a single well-defined responsibility:
// book_service.go - ONLY business logic
func (s *BookService) CreateBook(title, author, isbn string) (*domain.Book, error) {
book, err := domain.NewBook(title, author, isbn)
if err != nil {
return nil, err
}
return book, s.repository.Create(book)
}Code is open for extension but closed for modification:
// Easy to add new implementations
type PostgreSQLBookRepository struct { ... }
type MongoBookRepository struct { ... }
// All implement the same interface
type BookRepository interface {
Create(book *Book) error
FindByID(id string) (*Book, error)
// ...
}Any BookRepository implementation can replace another without breaking the code:
// Both work perfectly in BookService
bookService := service.NewBookService(repository.NewInMemoryBookRepository())
bookService := service.NewBookService(repository.NewPostgreSQLRepository())Lean interfaces with only necessary methods:
// Specific interface for book operations
type BookRepository interface {
Create(book *Book) error
FindByID(id string) (*Book, error)
FindAll() ([]*Book, error)
Update(book *Book) error
Delete(id string) error
}High-level modules don't depend on low-level modules, both depend on abstractions:
// Service depends on the INTERFACE, not the concrete implementation
type BookService struct {
repository domain.BookRepository // Interface, not concrete struct
}
// Manual dependency injection in main.go
bookRepository := repository.NewInMemoryBookRepository()
bookService := service.NewBookService(bookRepository)
bookHandler := handler.NewBookHandler(bookService)POST /books
Content-Type: application/json
{
"title": "Clean Code",
"author": "Robert C. Martin",
"isbn": "978-0132350884"
}GET /booksGET /books/{id}PUT /books/{id}
Content-Type: application/json
{
"title": "Clean Architecture",
"author": "Robert C. Martin",
"isbn": "978-0134494166"
}DELETE /books/{id}The API will be available at http://localhost:8080
# Create a book
curl -X POST http://localhost:8080/books \
-H "Content-Type: application/json" \
-d '{
"title": "Domain-Driven Design",
"author": "Eric Evans",
"isbn": "978-0321125215"
}'
# List all books
curl http://localhost:8080/books
# Get specific book
curl http://localhost:8080/books/{id}
# Update book
curl -X PUT http://localhost:8080/books/{id} \
-H "Content-Type: application/json" \
-d '{
"title": "DDD Distilled",
"author": "Vaughn Vernon",
"isbn": "978-0134434421"
}'
# Delete book
curl -X DELETE http://localhost:8080/books/{id}{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Clean Code",
"author": "Robert C. Martin",
"isbn": "978-0132350884",
"created_at": "2026-01-10T10:30:00Z",
"updated_at": "2026-01-10T10:30:00Z"
}{
"error": "book not found"
}# Clone repository
git clone https://github.com/Luuan11/solid.git
# Install dependencies
go mod tidy
# Run application
go run cmd/api/main.goMade with 💜 by Luan Fernando.