Skip to content

wgarunap/goconf

Repository files navigation

GoConf

A lightweight, flexible Go library for loading and validating environment-based configuration with beautiful output formatting.

Go Version License

Overview

GoConf simplifies configuration management in Go applications by providing:

  • Type-safe configuration - Parse environment variables and YAML files directly into Go structs
  • Multiple sources - Load configuration from environment variables or YAML files
  • Validation - Built-in validation using struct tags
  • Default values - Support for default values when environment variables are not set
  • Sensitive data masking - Automatically mask sensitive fields in output
  • Multiple output formats - Table format for development, JSON format for production
  • Zero configuration - Works out of the box with sensible defaults

Perfect for containerized applications, microservices, and cloud-native deployments where configuration is managed through environment variables following the 12-factor app methodology or structured YAML files.

Table of Contents

Installation

go get github.com/wgarunap/goconf

Quick Start

package main

import (
    "log"
    "github.com/wgarunap/goconf"
)

type Config struct {
    DatabaseURL string `env:"DATABASE_URL" validate:"required,uri"`
    Port        int    `env:"PORT" envDefault:"8080" validate:"gte=1024,lte=65535"`
    APIKey      string `env:"API_KEY" validate:"required" secret:"true"`
}

var AppConfig Config

func (Config) Register() error {
    return goconf.ParseEnv(&AppConfig)
}

func (Config) Validate() error {
    return goconf.StructValidator(AppConfig)
}

func (Config) Print() interface{} {
    return AppConfig
}

func main() {
    if err := goconf.Load(new(Config)); err != nil {
        log.Fatal(err)
    }

    log.Println("Configuration loaded successfully!")
}

Features

🔧 Environment Variable Parsing

  • Automatically parse environment variables into typed struct fields
  • Support for common Go types: string, int, bool, float64, etc.
  • Custom type support through struct tag configuration

✅ Built-in Validation

  • Powered by go-playground/validator
  • Extensive validation rules: required, uri, email, min, max, gte, lte, etc.
  • Custom validation rules support

🎨 Multiple Output Formats

Table Format (Default)

Beautiful Unicode table output for development environments:

┌─────────────┬───────────────────────────┐
│   CONFIG    │          VALUE            │
├─────────────┼───────────────────────────┤
│ DatabaseURL │ postgres://localhost:5432 │
│ Port        │ 8080                      │
│ APIKey      │ ***************           │
└─────────────┴───────────────────────────┘

JSON Format

Timestamped JSON output for production and centralized logging:

2026/01/31 10:30:15 {
  "DatabaseURL": "postgres://localhost:5432",
  "Port": 8080,
  "APIKey": "***************"
}

🔒 Sensitive Data Protection

Automatically mask sensitive fields marked with secret:"true" tag in all output formats.

📦 Default Values

Set fallback values using the envDefault tag when environment variables are not provided.

Usage

Environment Variables

GoConf supports loading configuration from environment variables with type-safe parsing.

  1. Define your configuration struct with environment variable mappings:
type AppConfig struct {
    // Basic string field
    AppName string `env:"APP_NAME" envDefault:"MyApp"`

    // Integer with validation
    Port int `env:"PORT" envDefault:"8080" validate:"gte=1024,lte=65535"`

    // Boolean flag
    Debug bool `env:"DEBUG" envDefault:"false"`

    // Required field with validation
    DatabaseURL string `env:"DATABASE_URL" validate:"required,uri"`

    // Sensitive data (will be masked in output)
    APISecret string `env:"API_SECRET" validate:"required" secret:"true"`
}
  1. Implement required interfaces:
var Config AppConfig

func (AppConfig) Register() error {
    return goconf.ParseEnv(&Config)
}

func (AppConfig) Validate() error {
    return goconf.StructValidator(Config)
}

func (AppConfig) Print() interface{} {
    return Config
}
  1. Load configuration:
func main() {
    if err := goconf.Load(new(AppConfig)); err != nil {
        log.Fatalf("Failed to load config: %v", err)
    }

    // Use your configuration
    log.Printf("Starting %s on port %d", Config.AppName, Config.Port)
}

YAML Configuration

GoConf supports loading configuration from YAML files, perfect for local development and structured configuration files.

  1. Define your configuration struct with YAML tag mappings:
type AppConfig struct {
    AppName  string `yaml:"app_name"`
    Port     int    `yaml:"port"`
    Debug    bool   `yaml:"debug"`

    Database struct {
        Host     string `yaml:"host"`
        Port     int    `yaml:"port"`
        Username string `yaml:"username"`
        Password string `yaml:"password" secret:"true"`
    } `yaml:"database"`
}
  1. Create a YAML configuration file (config.yaml):
app_name: MyApp
port: 8080
debug: true

database:
  host: localhost
  port: 5432
  username: dbuser
  password: secretpass
  1. Implement the Register interface to load from YAML:
var Config AppConfig

func (AppConfig) Register() error {
    return goconf.ParseYaml(&Config, "config.yaml")
}

func (AppConfig) Validate() error {
    return goconf.StructValidator(Config)
}

func (AppConfig) Print() interface{} {
    return Config
}
  1. Load configuration:
func main() {
    if err := goconf.Load(new(AppConfig)); err != nil {
        log.Fatalf("Failed to load config: %v", err)
    }

    log.Printf("Starting %s on port %d", Config.AppName, Config.Port)
}

Output:

┌──────────┬────────────┐
│  CONFIG  │   VALUE    │
├──────────┼────────────┤
│ AppName  │ MyApp      │
│ Port     │ 8080       │
│ Debug    │ true       │
│ Database │ {map data} │
└──────────┴────────────┘

Note: YAML configuration works seamlessly with validation and output formatting, just like environment variables.

Struct Tags

GoConf uses struct tags to configure field behavior:

Tag Description Example
env Environment variable name env:"PORT"
yaml YAML field name yaml:"port"
envDefault Default value if env var not set envDefault:"8080"
validate Validation rules (comma-separated) validate:"required,uri"
secret Mark field as sensitive (masks in output) secret:"true"

Example with multiple tags:

type Config struct {
    Port     int    `yaml:"port" validate:"gte=1024,lte=65535"`
    Password string `yaml:"password" secret:"true"`
}

Validation

GoConf uses go-playground/validator for validation. Common validation rules:

Rule Description Example
required Field must be set validate:"required"
uri Must be a valid URI validate:"uri"
email Must be a valid email validate:"email"
url Must be a valid URL validate:"url"
min=N Minimum length (string) or value (number) validate:"min=3"
max=N Maximum length (string) or value (number) validate:"max=100"
gte=N Greater than or equal to validate:"gte=0"
lte=N Less than or equal to validate:"lte=100"
oneof=A B C Value must be one of the options validate:"oneof=dev staging prod"

Multiple rules:

Port int `env:"PORT" validate:"required,gte=1024,lte=65535"`

Output Formats

Table Format (Default)

Best for local development and debugging:

func main() {
    // Table format is used by default
    if err := goconf.Load(new(Config)); err != nil {
        log.Fatal(err)
    }
}

JSON Format

Ideal for production environments, containerized deployments, and centralized logging systems:

func main() {
    // Switch to JSON format
    goconf.SetOutputFormat(goconf.OutputFormatJSON)

    if err := goconf.Load(new(Config)); err != nil {
        log.Fatal(err)
    }
}

Environment-based format selection:

func main() {
    // Use JSON in production, table in development
    if os.Getenv("ENV") == "production" {
        goconf.SetOutputFormat(goconf.OutputFormatJSON)
    }

    if err := goconf.Load(new(Config)); err != nil {
        log.Fatal(err)
    }
}

Interfaces

Configer

Must be implemented by configuration structs.

type Configer interface {
    Register() error
}

Validater (Optional)

Implement to enable validation.

type Validater interface {
    Validate() error
}

Printer (Optional)

Implement to enable configuration output.

type Printer interface {
    Print() interface{}
}

Constants

const (
    OutputFormatTable OutputFormat = "table" // Default: Unicode table
    OutputFormatJSON  OutputFormat = "json"  // JSON with timestamps
)

Best Practices

1. Use Validation Rules

Always validate critical configuration fields:

type Config struct {
    APIKey string `env:"API_KEY" validate:"required,min=32"`
    Port   int    `env:"PORT" validate:"required,gte=1024,lte=65535"`
}

2. Provide Sensible Defaults

Use envDefault for non-critical configuration:

type Config struct {
    Port     int    `env:"PORT" envDefault:"8080"`
    LogLevel string `env:"LOG_LEVEL" envDefault:"info"`
}

3. Mark Sensitive Data

Always mark secrets and passwords:

type Config struct {
    APIKey   string `env:"API_KEY" secret:"true"`
    Password string `env:"DB_PASSWORD" secret:"true"`
}

4. Use Environment-Specific Formats

if os.Getenv("ENVIRONMENT") == "production" {
    goconf.SetOutputFormat(goconf.OutputFormatJSON)
}

5. Group Related Configuration

Organize configuration into logical groups:

type Config struct {
    Server   ServerConfig
    Database DBConfig
    Cache    CacheConfig
}

6. Document Environment Variables

Create a .env.example file:

# Application
APP_NAME=myapp
APP_VERSION=1.0.0

# Server
PORT=8080
HOST=0.0.0.0

# Database
DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp
DB_USER=postgres
DB_PASSWORD=secret

7. Fail Fast on Configuration Errors

func main() {
    if err := goconf.Load(new(Config)); err != nil {
        log.Fatalf("Configuration error: %v", err)
    }
}

Contributing

We welcome contributions! Here's how you can help:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Commit your changes: git commit -m 'Add amazing feature'
  4. Push to the branch: git push origin feature/amazing-feature
  5. Open a Pull Request

Development Setup

# Clone the repository
git clone https://github.com/wgarunap/goconf.git
cd goconf

# Install dependencies
go mod download

# Run tests
go test ./...

# Run tests with coverage
go test -v -cover ./...

Code Quality

  • Write clear, idiomatic Go code
  • Add tests for new features
  • Ensure all tests pass
  • Update documentation
  • Follow existing code style

License

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

Acknowledgments

Support


Made with ❤️ for the Go community

Packages

 
 
 

Contributors