717 lines
22 KiB
Plaintext
717 lines
22 KiB
Plaintext
---
|
|
alwaysApply: true
|
|
---
|
|
|
|
# Cursor Rules for Tender Management Go Backend
|
|
|
|
## Project Context
|
|
This is a Go backend API for a tender management system following Clean Architecture principles with minimal complexity, designed to be AI-friendly and easy to maintain.
|
|
|
|
## 🏗️ Architecture Guidelines
|
|
|
|
### Clean Architecture Layers
|
|
- **Domain Layer** (`internal/domain/`): Business entities, interfaces, and core business rules
|
|
- **Service Layer** (`internal/service/`): Business logic and use cases
|
|
- **Handler Layer** (`internal/handler/`): HTTP controllers and request/response handling
|
|
- **Repository Layer** (`internal/repository/`): Data access implementations
|
|
- **Infrastructure Layer** (`internal/infrastructure/`): External dependencies (DB, cache, queues)
|
|
|
|
### Dependency Rules
|
|
- Always depend on interfaces, not concrete implementations
|
|
- Use dependency injection through constructors
|
|
- Inner layers should never depend on outer layers
|
|
- All dependencies flow inward toward the domain
|
|
|
|
## 💻 Go Best Practices
|
|
|
|
### Code Structure
|
|
- Use standard Go project layout with `internal/` for private code
|
|
- Group related functionality in packages
|
|
- Keep packages focused on single responsibility
|
|
- Use meaningful package names (not generic like `utils` or `helpers`)
|
|
|
|
### Naming Conventions
|
|
- Use Go naming conventions: camelCase for private, PascalCase for public
|
|
- Interface names should describe what they do (e.g., `UserRepository`, `AuthService`)
|
|
- Use descriptive variable names, avoid abbreviations
|
|
- Constants should be in ALL_CAPS with underscores
|
|
|
|
### Error Handling
|
|
- Always handle errors explicitly, never ignore them
|
|
- Use structured error messages with context
|
|
- Wrap errors with additional context using `fmt.Errorf("context: %w", err)`
|
|
- Log errors at the point they occur with relevant fields
|
|
- Return domain-specific error types when appropriate
|
|
|
|
### Function Design
|
|
- Keep functions small and focused (max 20-30 lines)
|
|
- Use early returns to reduce nesting
|
|
- Validate inputs at function entry points
|
|
- Use descriptive parameter names
|
|
- Limit function parameters (max 3-4, use structs for more)
|
|
|
|
## 🔌 Interface Design
|
|
|
|
### Repository Interfaces
|
|
- Always create interfaces in the domain layer
|
|
- Use context.Context as first parameter for all methods
|
|
- Return domain entities, not database models
|
|
- Include common operations: Create, GetByID, Update, Delete, List
|
|
- Use specific query methods (e.g., `GetByEmail`, `GetActiveUsers`)
|
|
|
|
### Service Interfaces
|
|
- Define business operations clearly
|
|
- Use request/response DTOs for complex operations
|
|
- Include validation in service methods
|
|
- Handle business logic, not infrastructure concerns
|
|
|
|
## 📝 Logging Standards
|
|
|
|
### Using Zap Logger
|
|
- Always use structured logging with fields
|
|
- Include relevant context (user_id, request_id, etc.)
|
|
- Use appropriate log levels:
|
|
- `Debug`: Detailed debugging information
|
|
- `Info`: General operational messages
|
|
- `Warn`: Warning conditions that should be addressed
|
|
- `Error`: Error conditions that need attention
|
|
- `Fatal`: Critical errors that cause program termination
|
|
|
|
### Logging Examples
|
|
```go
|
|
// Good
|
|
log.Info("User authenticated successfully", map[string]interface{}{
|
|
"user_id": user.ID.String(),
|
|
"email": user.Email,
|
|
"ip": clientIP,
|
|
})
|
|
|
|
// Bad
|
|
log.Info("User login")
|
|
```
|
|
|
|
### Error Logging
|
|
- Log errors with full context
|
|
- Include error details and relevant fields
|
|
- Don't log the same error multiple times in the call stack
|
|
|
|
## 🗄️ Database & Repository Patterns
|
|
|
|
### Repository Implementation
|
|
- Implement repository interfaces in `internal/repository/`
|
|
- Use proper database transactions for related operations
|
|
- Handle database errors gracefully
|
|
- Use prepared statements or ORM query builders
|
|
- Implement proper pagination
|
|
|
|
### Data Models
|
|
- Separate database models from domain entities
|
|
- Convert between database models and domain entities in repositories
|
|
- Use proper database field tags (bson, json)
|
|
- Include audit fields (created_at, updated_at)
|
|
|
|
## 🌐 HTTP Handler Guidelines
|
|
|
|
### Request Handling
|
|
- Validate all incoming requests using struct tags
|
|
- Use proper HTTP status codes
|
|
- Return consistent API response format using `pkg/response`
|
|
- Handle CORS appropriately
|
|
- Include request timeout handling
|
|
|
|
### Response Format
|
|
- Always use standardized response structure from `pkg/response`
|
|
- Include appropriate metadata for paginated responses
|
|
- Provide meaningful error messages
|
|
- Never expose internal errors to clients
|
|
|
|
### Security
|
|
- Validate and sanitize all inputs
|
|
- Use proper authentication middleware
|
|
- Implement rate limiting
|
|
- Never log sensitive information (passwords, tokens)
|
|
- Use HTTPS in production
|
|
|
|
## 🧪 Testing Guidelines
|
|
|
|
### Test Structure
|
|
- Write unit tests for all business logic
|
|
- Use table-driven tests for multiple scenarios
|
|
- Mock external dependencies using interfaces
|
|
- Test error cases, not just happy paths
|
|
- Use meaningful test names that describe the scenario
|
|
|
|
### Test Organization
|
|
- Place tests in same package as code being tested
|
|
- Use `_test.go` suffix for test files
|
|
- Create test utilities in `testutil` package if needed
|
|
- Use setup/teardown functions for common test data
|
|
|
|
## 📋 Configuration Management
|
|
|
|
### Configuration Files
|
|
- Use YAML for configuration files
|
|
- Support environment variable overrides
|
|
- Validate configuration on startup
|
|
- Use default values for optional settings
|
|
- Document all configuration options
|
|
|
|
### Environment Variables
|
|
- Use consistent naming convention (e.g., `TM_DATABASE_URI`)
|
|
- Never commit secrets in configuration files
|
|
- Use different configs for different environments
|
|
|
|
## 🚀 Performance Guidelines
|
|
|
|
### Optimization
|
|
- Use database indexes appropriately
|
|
- Implement caching for frequently accessed data
|
|
- Use connection pooling for databases
|
|
- Avoid N+1 queries
|
|
- Profile performance bottlenecks
|
|
|
|
### Memory Management
|
|
- Close resources properly (database connections, files)
|
|
- Use context for cancellation and timeouts
|
|
- Avoid memory leaks in goroutines
|
|
- Use sync.Pool for frequently allocated objects
|
|
|
|
## 📚 Documentation Standards
|
|
|
|
### Code Documentation
|
|
- Write clear comments for complex business logic
|
|
- Document all public interfaces and types
|
|
- Use Go doc comments format
|
|
- Include examples for complex functions
|
|
- Keep comments up to date with code changes
|
|
|
|
### API Documentation
|
|
- Use OpenAPI/Swagger annotations
|
|
- Document all endpoints with examples
|
|
- Include error response examples
|
|
- Document authentication requirements
|
|
|
|
## 🔐 Security Best Practices
|
|
|
|
### Authentication & Authorization
|
|
- Use JWT tokens with proper expiration
|
|
- Implement refresh token rotation
|
|
- Use bcrypt for password hashing
|
|
- Validate token claims properly
|
|
- Implement proper RBAC
|
|
|
|
### Input Validation
|
|
- Validate all inputs at API boundaries
|
|
- Use whitelist validation, not blacklist
|
|
- Sanitize inputs to prevent injection attacks
|
|
- Validate file uploads properly
|
|
|
|
## 📦 Dependency Management
|
|
|
|
### Go Modules
|
|
- Keep go.mod clean and organized
|
|
- Pin major versions for stability
|
|
- Regular dependency updates with testing
|
|
- Remove unused dependencies
|
|
- Use vendor directory for critical dependencies
|
|
|
|
### External Libraries
|
|
- Prefer standard library when possible
|
|
- Choose well-maintained libraries
|
|
- Avoid dependencies with security issues
|
|
- Keep dependencies minimal
|
|
|
|
## 🔄 Code Review Guidelines
|
|
|
|
### Before Committing
|
|
- Run `go fmt`, `go vet`, and linting tools
|
|
- Ensure all tests pass
|
|
- Check for proper error handling
|
|
- Verify logging is appropriate
|
|
- Confirm no sensitive data is exposed
|
|
|
|
### Code Quality
|
|
- Follow single responsibility principle
|
|
- Avoid code duplication
|
|
- Use meaningful variable names
|
|
- Keep functions and files reasonably sized
|
|
- Maintain consistent code style
|
|
|
|
## 🚨 Error Patterns to Avoid
|
|
|
|
### Anti-patterns
|
|
- Don't use panic for regular error handling
|
|
- Avoid global variables for application state
|
|
- Don't ignore context cancellation
|
|
- Avoid deeply nested if statements
|
|
- Don't use reflection unless absolutely necessary
|
|
|
|
### Common Mistakes
|
|
- Not handling database connection errors
|
|
- Forgetting to close resources
|
|
- Not validating user inputs
|
|
- Exposing internal errors to clients
|
|
- Not using proper HTTP status codes
|
|
|
|
## 📋 Checklist for New Features
|
|
|
|
### Before Implementation
|
|
- [ ] Define interfaces in domain layer
|
|
- [ ] Create proper request/response DTOs
|
|
- [ ] Plan error handling strategy
|
|
- [ ] Design database schema if needed
|
|
- [ ] Consider caching requirements
|
|
|
|
### During Implementation
|
|
- [ ] Follow clean architecture layers
|
|
- [ ] Use dependency injection
|
|
- [ ] Implement proper logging
|
|
- [ ] Add input validation
|
|
- [ ] Handle errors gracefully
|
|
|
|
### After Implementation
|
|
- [ ] Write unit tests
|
|
- [ ] Update API documentation
|
|
- [ ] Test error scenarios
|
|
- [ ] Verify security implications
|
|
- [ ] Check performance impact
|
|
|
|
## 🎯 Code Examples
|
|
|
|
### Service Implementation Template
|
|
```go
|
|
type UserServiceImpl struct {
|
|
userRepo domain.UserRepository
|
|
logger logger.Logger
|
|
}
|
|
|
|
func NewUserService(userRepo domain.UserRepository, logger logger.Logger) domain.UserService {
|
|
return &UserServiceImpl{
|
|
userRepo: userRepo,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
func (s *UserServiceImpl) CreateUser(ctx context.Context, req domain.CreateUserRequest) (*domain.User, error) {
|
|
// Validate input
|
|
if err := validateCreateUserRequest(req); err != nil {
|
|
return nil, fmt.Errorf("invalid request: %w", err)
|
|
}
|
|
|
|
// Business logic
|
|
user := &domain.User{
|
|
ID: uuid.New(),
|
|
Email: req.Email,
|
|
// ... other fields
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
|
|
// Repository call
|
|
if err := s.userRepo.Create(ctx, user); err != nil {
|
|
s.logger.Error("Failed to create user", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"email": req.Email,
|
|
})
|
|
return nil, fmt.Errorf("failed to create user: %w", err)
|
|
}
|
|
|
|
s.logger.Info("User created successfully", map[string]interface{}{
|
|
"user_id": user.ID.String(),
|
|
"email": user.Email,
|
|
})
|
|
|
|
return user, nil
|
|
}
|
|
```
|
|
|
|
### Handler Implementation Template
|
|
```go
|
|
func (h *UserHandler) CreateUser(c echo.Context) error {
|
|
var req domain.CreateUserRequest
|
|
|
|
// Bind and validate request
|
|
if err := c.Bind(&req); err != nil {
|
|
return response.BadRequest(c, "Invalid request format", err.Error())
|
|
}
|
|
|
|
if err := h.validator.Struct(&req); err != nil {
|
|
return response.ValidationError(c, "Validation failed", err.Error())
|
|
}
|
|
|
|
// Call service
|
|
user, err := h.userService.CreateUser(c.Request().Context(), req)
|
|
if err != nil {
|
|
h.logger.Error("Create user failed", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"email": req.Email,
|
|
})
|
|
return response.InternalServerError(c, "Failed to create user")
|
|
}
|
|
|
|
return response.Created(c, user, "User created successfully")
|
|
}
|
|
```
|
|
|
|
## 🚀 Remember
|
|
- Prioritize simplicity and readability over cleverness
|
|
- Make code self-documenting through clear naming
|
|
- Always consider the person who will maintain this code
|
|
- Test your code thoroughly
|
|
- Security and performance are not optional # Cursor Rules for Tender Management Go Backend
|
|
|
|
## Project Context
|
|
This is a Go backend API for a tender management system following Clean Architecture principles with minimal complexity, designed to be AI-friendly and easy to maintain.
|
|
|
|
## 🏗️ Architecture Guidelines
|
|
|
|
### Clean Architecture Layers
|
|
- **Domain Layer** (`internal/domain/`): Business entities, interfaces, and core business rules
|
|
- **Service Layer** (`internal/service/`): Business logic and use cases
|
|
- **Handler Layer** (`internal/handler/`): HTTP controllers and request/response handling
|
|
- **Repository Layer** (`internal/repository/`): Data access implementations
|
|
- **Infrastructure Layer** (`internal/infrastructure/`): External dependencies (DB, cache, queues)
|
|
|
|
### Dependency Rules
|
|
- Always depend on interfaces, not concrete implementations
|
|
- Use dependency injection through constructors
|
|
- Inner layers should never depend on outer layers
|
|
- All dependencies flow inward toward the domain
|
|
|
|
## 💻 Go Best Practices
|
|
|
|
### Code Structure
|
|
- Use standard Go project layout with `internal/` for private code
|
|
- Group related functionality in packages
|
|
- Keep packages focused on single responsibility
|
|
- Use meaningful package names (not generic like `utils` or `helpers`)
|
|
|
|
### Naming Conventions
|
|
- Use Go naming conventions: camelCase for private, PascalCase for public
|
|
- Interface names should describe what they do (e.g., `UserRepository`, `AuthService`)
|
|
- Use descriptive variable names, avoid abbreviations
|
|
- Constants should be in ALL_CAPS with underscores
|
|
|
|
### Error Handling
|
|
- Always handle errors explicitly, never ignore them
|
|
- Use structured error messages with context
|
|
- Wrap errors with additional context using `fmt.Errorf("context: %w", err)`
|
|
- Log errors at the point they occur with relevant fields
|
|
- Return domain-specific error types when appropriate
|
|
|
|
### Function Design
|
|
- Keep functions small and focused (max 20-30 lines)
|
|
- Use early returns to reduce nesting
|
|
- Validate inputs at function entry points
|
|
- Use descriptive parameter names
|
|
- Limit function parameters (max 3-4, use structs for more)
|
|
|
|
## 🔌 Interface Design
|
|
|
|
### Repository Interfaces
|
|
- Always create interfaces in the domain layer
|
|
- Use context.Context as first parameter for all methods
|
|
- Return domain entities, not database models
|
|
- Include common operations: Create, GetByID, Update, Delete, List
|
|
- Use specific query methods (e.g., `GetByEmail`, `GetActiveUsers`)
|
|
|
|
### Service Interfaces
|
|
- Define business operations clearly
|
|
- Use request/response DTOs for complex operations
|
|
- Include validation in service methods
|
|
- Handle business logic, not infrastructure concerns
|
|
|
|
## 📝 Logging Standards
|
|
|
|
### Using Zap Logger
|
|
- Always use structured logging with fields
|
|
- Include relevant context (user_id, request_id, etc.)
|
|
- Use appropriate log levels:
|
|
- `Debug`: Detailed debugging information
|
|
- `Info`: General operational messages
|
|
- `Warn`: Warning conditions that should be addressed
|
|
- `Error`: Error conditions that need attention
|
|
- `Fatal`: Critical errors that cause program termination
|
|
|
|
### Logging Examples
|
|
```go
|
|
// Good
|
|
log.Info("User authenticated successfully", map[string]interface{}{
|
|
"user_id": user.ID.String(),
|
|
"email": user.Email,
|
|
"ip": clientIP,
|
|
})
|
|
|
|
// Bad
|
|
log.Info("User login")
|
|
```
|
|
|
|
### Error Logging
|
|
- Log errors with full context
|
|
- Include error details and relevant fields
|
|
- Don't log the same error multiple times in the call stack
|
|
|
|
## 🗄️ Database & Repository Patterns
|
|
|
|
### Repository Implementation
|
|
- Implement repository interfaces in `internal/repository/`
|
|
- Use proper database transactions for related operations
|
|
- Handle database errors gracefully
|
|
- Use prepared statements or ORM query builders
|
|
- Implement proper pagination
|
|
|
|
### Data Models
|
|
- Separate database models from domain entities
|
|
- Convert between database models and domain entities in repositories
|
|
- Use proper database field tags (bson, json)
|
|
- Include audit fields (created_at, updated_at)
|
|
|
|
## 🌐 HTTP Handler Guidelines
|
|
|
|
### Request Handling
|
|
- Validate all incoming requests using struct tags
|
|
- Use proper HTTP status codes
|
|
- Return consistent API response format using `pkg/response`
|
|
- Handle CORS appropriately
|
|
- Include request timeout handling
|
|
|
|
### Response Format
|
|
- Always use standardized response structure from `pkg/response`
|
|
- Include appropriate metadata for paginated responses
|
|
- Provide meaningful error messages
|
|
- Never expose internal errors to clients
|
|
|
|
### Security
|
|
- Validate and sanitize all inputs
|
|
- Use proper authentication middleware
|
|
- Implement rate limiting
|
|
- Never log sensitive information (passwords, tokens)
|
|
- Use HTTPS in production
|
|
|
|
## 🧪 Testing Guidelines
|
|
|
|
### Test Structure
|
|
- Write unit tests for all business logic
|
|
- Use table-driven tests for multiple scenarios
|
|
- Mock external dependencies using interfaces
|
|
- Test error cases, not just happy paths
|
|
- Use meaningful test names that describe the scenario
|
|
|
|
### Test Organization
|
|
- Place tests in same package as code being tested
|
|
- Use `_test.go` suffix for test files
|
|
- Create test utilities in `testutil` package if needed
|
|
- Use setup/teardown functions for common test data
|
|
|
|
## 📋 Configuration Management
|
|
|
|
### Configuration Files
|
|
- Use YAML for configuration files
|
|
- Support environment variable overrides
|
|
- Validate configuration on startup
|
|
- Use default values for optional settings
|
|
- Document all configuration options
|
|
|
|
### Environment Variables
|
|
- Use consistent naming convention (e.g., `TM_DATABASE_URI`)
|
|
- Never commit secrets in configuration files
|
|
- Use different configs for different environments
|
|
|
|
## 🚀 Performance Guidelines
|
|
|
|
### Optimization
|
|
- Use database indexes appropriately
|
|
- Implement caching for frequently accessed data
|
|
- Use connection pooling for databases
|
|
- Avoid N+1 queries
|
|
- Profile performance bottlenecks
|
|
|
|
### Memory Management
|
|
- Close resources properly (database connections, files)
|
|
- Use context for cancellation and timeouts
|
|
- Avoid memory leaks in goroutines
|
|
- Use sync.Pool for frequently allocated objects
|
|
|
|
## 📚 Documentation Standards
|
|
|
|
### Code Documentation
|
|
- Write clear comments for complex business logic
|
|
- Document all public interfaces and types
|
|
- Use Go doc comments format
|
|
- Include examples for complex functions
|
|
- Keep comments up to date with code changes
|
|
|
|
### API Documentation
|
|
- Use OpenAPI/Swagger annotations
|
|
- Document all endpoints with examples
|
|
- Include error response examples
|
|
- Document authentication requirements
|
|
|
|
## 🔐 Security Best Practices
|
|
|
|
### Authentication & Authorization
|
|
- Use JWT tokens with proper expiration
|
|
- Implement refresh token rotation
|
|
- Use bcrypt for password hashing
|
|
- Validate token claims properly
|
|
- Implement proper RBAC
|
|
|
|
### Input Validation
|
|
- Validate all inputs at API boundaries
|
|
- Use whitelist validation, not blacklist
|
|
- Sanitize inputs to prevent injection attacks
|
|
- Validate file uploads properly
|
|
|
|
## 📦 Dependency Management
|
|
|
|
### Go Modules
|
|
- Keep go.mod clean and organized
|
|
- Pin major versions for stability
|
|
- Regular dependency updates with testing
|
|
- Remove unused dependencies
|
|
- Use vendor directory for critical dependencies
|
|
|
|
### External Libraries
|
|
- Prefer standard library when possible
|
|
- Choose well-maintained libraries
|
|
- Avoid dependencies with security issues
|
|
- Keep dependencies minimal
|
|
|
|
## 🔄 Code Review Guidelines
|
|
|
|
### Before Committing
|
|
- Run `go fmt`, `go vet`, and linting tools
|
|
- Ensure all tests pass
|
|
- Check for proper error handling
|
|
- Verify logging is appropriate
|
|
- Confirm no sensitive data is exposed
|
|
|
|
### Code Quality
|
|
- Follow single responsibility principle
|
|
- Avoid code duplication
|
|
- Use meaningful variable names
|
|
- Keep functions and files reasonably sized
|
|
- Maintain consistent code style
|
|
|
|
## 🚨 Error Patterns to Avoid
|
|
|
|
### Anti-patterns
|
|
- Don't use panic for regular error handling
|
|
- Avoid global variables for application state
|
|
- Don't ignore context cancellation
|
|
- Avoid deeply nested if statements
|
|
- Don't use reflection unless absolutely necessary
|
|
|
|
### Common Mistakes
|
|
- Not handling database connection errors
|
|
- Forgetting to close resources
|
|
- Not validating user inputs
|
|
- Exposing internal errors to clients
|
|
- Not using proper HTTP status codes
|
|
|
|
## 📋 Checklist for New Features
|
|
|
|
### Before Implementation
|
|
- [ ] Define interfaces in domain layer
|
|
- [ ] Create proper request/response DTOs
|
|
- [ ] Plan error handling strategy
|
|
- [ ] Design database schema if needed
|
|
- [ ] Consider caching requirements
|
|
|
|
### During Implementation
|
|
- [ ] Follow clean architecture layers
|
|
- [ ] Use dependency injection
|
|
- [ ] Implement proper logging
|
|
- [ ] Add input validation
|
|
- [ ] Handle errors gracefully
|
|
|
|
### After Implementation
|
|
- [ ] Write unit tests
|
|
- [ ] Update API documentation
|
|
- [ ] Test error scenarios
|
|
- [ ] Verify security implications
|
|
- [ ] Check performance impact
|
|
|
|
## 🎯 Code Examples
|
|
|
|
### Service Implementation Template
|
|
```go
|
|
type UserServiceImpl struct {
|
|
userRepo domain.UserRepository
|
|
logger logger.Logger
|
|
}
|
|
|
|
func NewUserService(userRepo domain.UserRepository, logger logger.Logger) domain.UserService {
|
|
return &UserServiceImpl{
|
|
userRepo: userRepo,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
func (s *UserServiceImpl) CreateUser(ctx context.Context, req domain.CreateUserRequest) (*domain.User, error) {
|
|
// Validate input
|
|
if err := validateCreateUserRequest(req); err != nil {
|
|
return nil, fmt.Errorf("invalid request: %w", err)
|
|
}
|
|
|
|
// Business logic
|
|
user := &domain.User{
|
|
ID: uuid.New(),
|
|
Email: req.Email,
|
|
// ... other fields
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
|
|
// Repository call
|
|
if err := s.userRepo.Create(ctx, user); err != nil {
|
|
s.logger.Error("Failed to create user", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"email": req.Email,
|
|
})
|
|
return nil, fmt.Errorf("failed to create user: %w", err)
|
|
}
|
|
|
|
s.logger.Info("User created successfully", map[string]interface{}{
|
|
"user_id": user.ID.String(),
|
|
"email": user.Email,
|
|
})
|
|
|
|
return user, nil
|
|
}
|
|
```
|
|
|
|
### Handler Implementation Template
|
|
```go
|
|
func (h *UserHandler) CreateUser(c echo.Context) error {
|
|
var req domain.CreateUserRequest
|
|
|
|
// Bind and validate request
|
|
if err := c.Bind(&req); err != nil {
|
|
return response.BadRequest(c, "Invalid request format", err.Error())
|
|
}
|
|
|
|
if err := h.validator.Struct(&req); err != nil {
|
|
return response.ValidationError(c, "Validation failed", err.Error())
|
|
}
|
|
|
|
// Call service
|
|
user, err := h.userService.CreateUser(c.Request().Context(), req)
|
|
if err != nil {
|
|
h.logger.Error("Create user failed", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"email": req.Email,
|
|
})
|
|
return response.InternalServerError(c, "Failed to create user")
|
|
}
|
|
|
|
return response.Created(c, user, "User created successfully")
|
|
}
|
|
```
|
|
|
|
## 🚀 Remember
|
|
- Prioritize simplicity and readability over cleverness
|
|
- Make code self-documenting through clear naming
|
|
- Always consider the person who will maintain this code
|
|
- Test your code thoroughly
|
|
- Security and performance are not optional |