ezutil

package module
v2.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 2, 2026 License: MIT Imports: 16 Imported by: 5

README ΒΆ

EZUtil

CI Tests Go Report Card codecov Go Reference

A comprehensive, production-ready Go utility library that provides common functionality for web applications built with Gin, GORM, and other popular Go frameworks. EZUtil is designed to accelerate development by providing well-tested, reusable components for modern Go web applications.

πŸš€ Features

🌐 HTTP & Web Utilities
  • Gin Parameter Extraction: Type-safe parameter parsing with GetPathParam[T], GetQueryParam[T]
  • Request Binding: Simplified JSON/form data binding with validation
  • Response Helpers: Standardized JSON response utilities
  • Middleware Support: Common middleware implementations for web applications
  • Routing Utilities: Simplified routing helpers and patterns
πŸ—„οΈ Database & ORM
  • GORM Integration: Seamless database connection management and configuration
  • Query Scopes: Reusable, composable query scopes for common database operations
  • Transaction Management: Robust transaction utilities with nested transaction support
  • Multi-Database Support: MySQL and PostgreSQL drivers with automatic configuration
  • Connection Pooling: Optimized database connection management
πŸ”§ Configuration Management
  • Environment-Based Config: Automatic configuration loading from environment variables
  • Type-Safe Parsing: Built-in validation and type conversion for configuration values
  • Database Auto-Configuration: Automatic database connection setup with fallback defaults
  • Application Settings: Centralized management of app-level configuration
  • Flexible Loading: Support for loading configuration with or without database dependency
πŸ” Authentication & Security
  • JWT Service: Complete JWT token creation, verification, and management
  • Secure Token Handling: Built-in token expiration and refresh capabilities
  • Authentication Middleware: Ready-to-use authentication middleware for Gin
  • Security Best Practices: Implements industry-standard security patterns
πŸ› οΈ General Utilities
  • Type-Safe Parsing: Generic Parse[T] function for string-to-type conversion
  • String Utilities: Random string generation, manipulation, and validation
  • Time Management: Date/time formatting, manipulation, and timezone handling
  • Slice Operations: Functional programming utilities (MapSlice, MapSliceWithError)
  • Error Handling: Structured error types with HTTP context and stack traces
  • Template Integration: Seamless integration with Templ template engine
  • UUID Support: UUID generation, parsing, and validation utilities

πŸ“¦ Installation

go get github.com/itsLeonB/ezutil

Requirements:

  • Go 1.23 or higher
  • Compatible with Go 1.23, and 1.24

πŸƒ Quick Start

Basic Web Application
package main

import (
    "log"
    "time"
    
    "github.com/gin-gonic/gin"
    "github.com/itsLeonB/ezutil"
)

func main() {
    // Load configuration from environment
    defaults := ezutil.Config{
        App: &ezutil.App{
            Env:        "development",
            Port:       "8080",
            Timeout:    30 * time.Second,
            ClientUrls: []string{"http://localhost:8080"},
            Timezone:   "UTC",
        },
        Auth: &ezutil.Auth{
            SecretKey:      "your-secret-key",
            TokenDuration:  24 * time.Hour,
            CookieDuration: 7 * 24 * time.Hour,
            Issuer:         "your-app",
            URL:            "http://localhost:8080",
        },
    }
    
    config := ezutil.LoadConfig(defaults)
    
    // Create Gin router
    r := gin.Default()
    
    // Use EZUtil helpers for type-safe parameter extraction
    r.GET("/user/:id", func(c *gin.Context) {
        userID, exists, err := ezutil.GetPathParam[int](c, "id")
        if err != nil {
            c.JSON(400, gin.H{"error": "Invalid user ID format"})
            return
        }
        if !exists {
            c.JSON(400, gin.H{"error": "User ID is required"})
            return
        }
        
        c.JSON(200, gin.H{"user_id": userID, "message": "User found"})
    })
    
    // Start server
    log.Printf("Server starting on port %s", config.App.Port)
    r.Run(":" + config.App.Port)
}
Configuration Setup

Create a .env file or set environment variables:

# Application Configuration
APP_ENV=production
APP_PORT=8080
APP_TIMEOUT=30s
APP_TIMEZONE=UTC
APP_CLIENTURLS=http://localhost:8080,https://yourdomain.com

# Database Configuration
SQLDB_HOST=localhost
SQLDB_PORT=5432
SQLDB_NAME=myapp
SQLDB_USER=username
SQLDB_PASSWORD=password
SQLDB_DRIVER=postgres

# Authentication Configuration
AUTH_SECRETKEY=your-super-secret-jwt-key
AUTH_TOKENDURATION=24h
AUTH_COOKIEDURATION=168h
AUTH_ISSUER=myapp
AUTH_URL=https://yourdomain.com
Advanced Usage Examples
Database Operations with Transactions
// Initialize transactor
transactor := ezutil.NewTransactor(db)

// Use transactions with automatic rollback on error
err := transactor.WithinTransaction(ctx, func(ctx context.Context) error {
    tx, err := ezutil.GetTxFromContext(ctx)
    if err != nil {
        return err
    }
    
    // Perform database operations within transaction
    user := User{Name: "John Doe", Email: "john@example.com"}
    if err := tx.Create(&user).Error; err != nil {
        return err // Transaction will be rolled back automatically
    }
    
    // Nested transactions are supported
    return transactor.WithinTransaction(ctx, func(ctx context.Context) error {
        innerTx, err := ezutil.GetTxFromContext(ctx)
        if err != nil {
            return err
        }
        
        profile := Profile{UserID: user.ID, Bio: "Software Developer"}
        return innerTx.Create(&profile).Error
    })
})

if err != nil {
    log.Printf("Transaction failed: %v", err)
}
Type-Safe String Parsing
// Parse various types from strings
userID, err := ezutil.Parse[int]("123")
if err != nil {
    log.Printf("Invalid user ID: %v", err)
}

isActive, err := ezutil.Parse[bool]("true")
price, err := ezutil.Parse[float64]("29.99")
uuid, err := ezutil.Parse[uuid.UUID]("550e8400-e29b-41d4-a716-446655440000")

// Generate secure random strings
apiKey, err := ezutil.GenerateRandomString(32)
if err != nil {
    log.Printf("Failed to generate API key: %v", err)
}
Functional Slice Operations
// Transform slices with type safety
numbers := []int{1, 2, 3, 4, 5}
doubled := ezutil.MapSlice(numbers, func(n int) int {
    return n * 2
})
// Result: [2, 4, 6, 8, 10]

// Handle errors during transformation
strings := []string{"1", "2", "invalid", "4"}
numbers, err := ezutil.MapSliceWithError(strings, func(s string) (int, error) {
    return ezutil.Parse[int](s)
})
if err != nil {
    log.Printf("Conversion failed: %v", err)
}
Advanced Error Handling
// Create structured application errors
appErr := ezutil.NewAppError(
    "VALIDATION_ERROR",
    "Invalid input provided",
    http.StatusBadRequest,
    map[string]string{
        "field": "email",
        "issue": "invalid format",
    },
)

// Use in Gin handlers with automatic error response
r.POST("/users", func(c *gin.Context) {
    var user User
    if err := c.ShouldBindJSON(&user); err != nil {
        ezutil.HandleError(c, ezutil.NewAppError(
            "BIND_ERROR",
            "Invalid JSON payload",
            http.StatusBadRequest,
            nil,
        ))
        return
    }
    
    // Process user...
})
JWT Authentication
// Create JWT service
jwtService := ezutil.NewJWTService(config.Auth.SecretKey, config.Auth.Issuer)

// Generate tokens
claims := map[string]interface{}{
    "user_id": 123,
    "role":    "admin",
}

token, err := jwtService.GenerateToken(claims, config.Auth.TokenDuration)
if err != nil {
    log.Printf("Token generation failed: %v", err)
}

// Verify tokens
parsedClaims, err := jwtService.VerifyToken(token)
if err != nil {
    log.Printf("Token verification failed: %v", err)
}

πŸ—οΈ Project Structure

ezutil/
β”œβ”€β”€ .github/
β”‚   └── workflows/           # CI/CD workflows
β”‚       β”œβ”€β”€ ci.yml          # Main CI pipeline
β”‚       β”œβ”€β”€ test.yml        # Extended testing with security scans
β”‚       └── lint.yml        # Code linting
β”œβ”€β”€ internal/              # Internal utilities
β”‚   └── *_test.go          # Internal package tests
β”œβ”€β”€ config_loader.go       # Environment configuration loading
β”œβ”€β”€ errors.go              # Error handling utilities
β”œβ”€β”€ gin_*.go              # Gin framework utilities
β”œβ”€β”€ gorm_*.go             # GORM database utilities
β”œβ”€β”€ http_utils.go         # HTTP utilities
β”œβ”€β”€ services.go           # Service layer utilities (JWT, etc.)
β”œβ”€β”€ slice_utils.go        # Slice manipulation utilities
β”œβ”€β”€ sql_utils.go          # SQL utilities
β”œβ”€β”€ string_utils.go       # String manipulation utilities
β”œβ”€β”€ templ_utils.go        # Template utilities
β”œβ”€β”€ time_utils.go         # Time/date utilities
β”œβ”€β”€ uuid_utils.go         # UUID utilities
β”œβ”€β”€ Makefile              # Build and test automation
β”œβ”€β”€ go.mod                # Go module definition
└── README.md             # This file

πŸ§ͺ Testing

EZUtil includes a comprehensive test suite with over 200 individual test cases covering all exported functions and methods. The tests are organized alongside their respective source files using the ezutil_test package for proper isolation.

Test Coverage

The test suite provides comprehensive coverage including:

  • βœ… All exported functions and methods - 100% coverage of public API
  • βœ… Happy path scenarios - Normal operation testing
  • βœ… Error conditions - Comprehensive error handling validation
  • βœ… Edge cases - Boundary condition testing
  • βœ… Database operations - Using in-memory SQLite for isolation
  • βœ… HTTP request/response handling - Complete web layer testing
  • βœ… JWT token operations - Authentication flow testing
  • βœ… Configuration loading - Environment variable processing
  • βœ… Transaction management - Database transaction testing
  • βœ… Type safety - Generic function validation
Running Tests

Use the provided Makefile commands for various testing scenarios:

# Show all available commands
make help

# Run all tests (quick)
make test

# Run tests with verbose output
make test-verbose

# Run tests with coverage report
make test-coverage

# Generate HTML coverage report
make test-coverage-html

# Clean test cache and run fresh tests
make test-clean
Continuous Integration

The project uses GitHub Actions for comprehensive CI/CD:

Main CI Pipeline (ci.yml)
  • Multi-version testing: Go 1.23, 1.24
  • Automated testing: Full test suite execution
  • Coverage reporting: Automatic upload to Codecov
  • Build verification: Cross-version compatibility
Extended Testing (test.yml)
  • Comprehensive testing: All test scenarios
  • Security scanning: Gosec static analysis
  • Dependency verification: Module integrity checks
  • SARIF reporting: Security findings integration
Code Quality (lint.yml)
  • Static analysis: golangci-lint integration
  • Code formatting: Automated style checking
  • Best practices: Go idiom enforcement
Test Organization
Tests are co-located with their respective source files:
β”œβ”€β”€ generic_mappers_test.go  # Generic mapper tests
β”œβ”€β”€ slice_utils_test.go      # Slice operation tests
β”œβ”€β”€ sql_utils_test.go        # SQL utility tests
β”œβ”€β”€ string_utils_test.go     # String manipulation tests
β”œβ”€β”€ time_utils_test.go       # Time/date utility tests
β”œβ”€β”€ uuid_utils_test.go       # UUID utility tests
└── internal/
    └── simple_logger_test.go # Internal logger tests

πŸ“š Dependencies

EZUtil builds upon several excellent Go packages:

Core Dependencies
  • Gin v1.9.1 - HTTP web framework
  • GORM v1.25.5 - ORM library for database operations
  • Eris v0.8.1 - Error handling and stack traces
  • JWT v5.2.0 - JSON Web Token implementation
Database Drivers
Utility Libraries
  • Templ v0.2.543 - Template engine integration
  • Envconfig v1.4.0 - Environment variable configuration
  • UUID v1.4.0 - UUID generation and parsing
Development Dependencies

πŸ”§ Configuration Reference

Application Configuration (APP_*)
Variable Type Default Description
APP_ENV string development Application environment
APP_PORT string 3000 Server port number
APP_TIMEOUT duration 10s Request timeout
APP_CLIENTURLS []string ["http://localhost:3000"] Allowed client URLs
APP_TIMEZONE string America/New_York Application timezone
Database Configuration (SQLDB_*)
Variable Type Required Description
SQLDB_HOST string βœ… Database host
SQLDB_PORT string βœ… Database port
SQLDB_NAME string βœ… Database name
SQLDB_USER string βœ… Database username
SQLDB_PASSWORD string βœ… Database password
SQLDB_DRIVER string βœ… Database driver (mysql or postgres)
Authentication Configuration (AUTH_*)
Variable Type Default Description
AUTH_SECRETKEY string default-secret JWT signing key
AUTH_TOKENDURATION duration 30m JWT token lifetime
AUTH_COOKIEDURATION duration 12h Cookie lifetime
AUTH_ISSUER string default-issuer JWT issuer
AUTH_URL string http://localhost:3000 Authentication service URL

πŸš€ Performance & Best Practices

Database Optimization
  • Connection Pooling: Automatic connection pool management
  • Transaction Efficiency: Nested transaction support with proper rollback
  • Query Optimization: Reusable scopes for common query patterns
  • Type Safety: Compile-time type checking for database operations
Security Features
  • JWT Security: Secure token generation with configurable expiration
  • Input Validation: Built-in parameter validation and sanitization
  • Error Handling: Structured errors without sensitive information leakage
  • HTTPS Support: Ready for production HTTPS deployment
Development Experience
  • Type Safety: Generic functions for compile-time type checking
  • Error Context: Rich error information with stack traces
  • Testing Support: Comprehensive test utilities and mocks
  • Documentation: Extensive inline documentation and examples

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Development Setup
  1. Fork and Clone

    git clone https://github.com/yourusername/ezutil.git
    cd ezutil
    
  2. Install Dependencies

    go mod download
    cd test && go mod download
    
  3. Run Tests

    make test-verbose
    
  4. Run Linting

    make lint
    
Contribution Guidelines
  1. Code Quality: Ensure all tests pass and maintain test coverage
  2. Documentation: Update documentation for new features
  3. Commit Messages: Use clear, descriptive commit messages
  4. Pull Requests: Include description of changes and test results
Development Workflow
  1. Create your feature branch (git checkout -b feature/amazing-feature)
  2. Make your changes and add tests
  3. Ensure all tests pass (make test)
  4. Run linting (make lint)
  5. Commit your changes (git commit -m 'Add some amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ‘¨β€πŸ’» Author

Ellion Blessan - itsLeonB

πŸ™ Acknowledgments

  • The Go community for excellent libraries and tools
  • Contributors who help improve this project
  • Users who provide feedback and bug reports

EZUtil - Making Go web development easier, one utility at a time. πŸš€

Built with ❀️ for the Go community

Documentation ΒΆ

Overview ΒΆ

Package ezutil provides utility functions for Go applications.

Index ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

This section is empty.

Functions ΒΆ

func Capitalize ΒΆ

func Capitalize(word string) string

Capitalize converts the first character of a word to uppercase and the rest to lowercase. Returns an empty string if the input is empty. Useful for formatting names and titles consistently.

func CompareUUID ΒΆ

func CompareUUID(a, b uuid.UUID) int

CompareUUID compares two UUID values byte by byte. Returns -1 if a < b, 0 if a == b, and 1 if a > b. Useful for sorting UUIDs or implementing custom comparison logic.

func DecimalToMoney ΒΆ added in v2.1.0

func DecimalToMoney(d decimal.Decimal, currencyCode string) *money.Money

func DecimalToMoneyRounded ΒΆ added in v2.1.0

func DecimalToMoneyRounded(d decimal.Decimal, currencyCode string) *money.Money

DecimalToMoneyRounded converts decimal to Money with proper rounding This handles cases where decimal has more precision than nanos can represent

func FormatTimeNullable ΒΆ

func FormatTimeNullable(t time.Time, layout string) string

FormatTimeNullable formats a time.Time using the specified layout, handling zero values gracefully. Returns an empty string if the time is zero (uninitialized), otherwise returns the formatted time. Useful for optional time fields in JSON responses and templates.

func FromProtoTime ΒΆ added in v2.1.0

func FromProtoTime(t *timestamppb.Timestamp) time.Time

func GenerateRandomString ΒΆ

func GenerateRandomString(length int) (string, error)

GenerateRandomString creates a cryptographically secure random string of the specified length. The string is base64-encoded using URL-safe encoding without padding. Returns an error if length is non-positive or random generation fails.

func GetEndOfDay ΒΆ

func GetEndOfDay(year int, month int, day int) (time.Time, error)

GetEndOfDay creates a time.Time representing the end of the specified date (23:59:59.999999999 UTC). It validates the date parameters and returns an error for invalid dates. The returned time is in UTC timezone with maximum precision.

func GetStartOfDay ΒΆ

func GetStartOfDay(year int, month int, day int) (time.Time, error)

GetStartOfDay creates a time.Time representing the start of the specified date (00:00:00 UTC). It validates the date parameters and returns an error for invalid dates. The returned time is in UTC timezone.

func GetTimeRangeClause ΒΆ

func GetTimeRangeClause(timeCol string, start, end time.Time) (string, []any)

GetTimeRangeClause generates a SQL WHERE clause for time range filtering. It handles various combinations of start and end times, including open-ended ranges. Returns the SQL clause string and corresponding parameter values for prepared statements.

func MapSlice ΒΆ

func MapSlice[T any, U any](input []T, mapperFunc func(T) U) []U

MapSlice applies a mapping function to each element of an input slice and returns a new slice. The function transforms elements of type T to type U using the provided mapperFunc. This is a generic utility for functional-style slice transformations.

func MapSliceWithError ΒΆ

func MapSliceWithError[T any, U any](input []T, mapperFunc func(T) (U, error)) ([]U, error)

MapSliceWithError applies a mapping function to each element of an input slice with error handling. The function transforms elements of type T to type U using the provided mapperFunc. Returns an error immediately if any transformation fails, providing fail-fast behavior.

func MeasureLatency ΒΆ added in v2.2.0

func MeasureLatency(f func()) time.Duration

MeasureLatency measures and returns the execution duration of the provided function.

func MoneyToDecimal ΒΆ added in v2.1.0

func MoneyToDecimal(m *money.Money) decimal.Decimal

MoneyToDecimal converts google.type.Money to decimal.Decimal

func Parse ΒΆ

func Parse[T any](value string) (T, error)

Parse converts a string value to the specified type T. Supported types include string, int, bool, and uuid.UUID. Returns an error if parsing fails or the type is unsupported.

func Unmarshal ΒΆ added in v2.3.0

func Unmarshal[T any](data []byte) (T, error)

func ValidateMoney ΒΆ added in v2.1.0

func ValidateMoney(m *money.Money) error

ValidateMoney checks if Money values are valid

Types ΒΆ

type Logger ΒΆ

type Logger interface {
	Debug(args ...any)
	Info(args ...any)
	Warn(args ...any)
	Error(args ...any)
	Fatal(args ...any)
	Debugf(format string, args ...any)
	Infof(format string, args ...any)
	Warnf(format string, args ...any)
	Errorf(format string, args ...any)
	Fatalf(format string, args ...any)

	WithError(err error) Logger
	WithField(key string, value any) Logger
	WithFields(fields map[string]any) Logger
	WithContext(ctx context.Context) Logger

	goose.Logger
}

Directories ΒΆ

Path Synopsis
Package gorm provides logger that implements gorm's logger.Interface
Package gorm provides logger that implements gorm's logger.Interface
Package otel implements instrumented zerolog logger
Package otel implements instrumented zerolog logger
Package simple provides simple implementation of Logger that logs to STDOUT
Package simple provides simple implementation of Logger that logs to STDOUT
Package zerolog provides Logger implementation that uses zerolog under the hood
Package zerolog provides Logger implementation that uses zerolog under the hood

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL