Skip to content

m0rjc/goconfig

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

38 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

goconfig

A simple, type-safe Go library for loading configuration from environment variables using struct tags.

Features

  • 🏷️ Struct-based configuration - Define config with Go structs and tags
  • βœ… Built-in validation - min, max, and pattern tags plus custom type validators (docs | example)
  • 🎯 Type-safe - Automatic conversion for primitives, durations, and JSON with generic type handlers
  • 🧱 Building block architecture - Compose custom types from simple, reusable components (docs)
  • πŸ”„ Flexible defaults - Struct tags or pre-initialized values (docs)
  • 🌳 Nested structs - Organize configuration hierarchically
  • πŸ”§ Extensible - Custom types and key stores (docs)
  • πŸ’¬ Clear errors - Descriptive validation and missing field errors

Installation

go get github.com/m0rjc/goconfig

Quick Start

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/m0rjc/goconfig"
)

type Config struct {
    // Basic fields
    APIKey string `key:"API_KEY" required:"true"`
    Host   string `key:"HOST" default:"localhost"`

    // With validation
    Port    int           `key:"PORT" default:"8080" min:"1024" max:"65535"`
    Timeout time.Duration `key:"TIMEOUT" default:"30s" min:"1s" max:"5m"`

    // Nested configuration
    Database struct {
        Host     string `key:"DB_HOST" default:"localhost"`
        Port     int    `key:"DB_PORT" default:"5432"`
        Username string `key:"DB_USER" required:"true"`
        Password string `key:"DB_PASSWORD" required:"true"`
    }
}

func main() {
    var config Config

    if err := goconfig.Load(context.Background(), &config); err != nil {
        log.Fatalf("Failed to load configuration: %v", err)
    }

    fmt.Printf("Server: %s:%d\n", config.Host, config.Port)
    fmt.Printf("Database: %s:%d\n", config.Database.Host, config.Database.Port)
}

Set environment variables and run:

export API_KEY="sk-your-api-key"
export DB_USER="appuser"
export DB_PASSWORD="secret"
export PORT="8080"
go run main.go

Struct Tags

Tag Purpose Example
key Environment variable name (required) key:"PORT"
default Default value if not set default:"8080"
min Minimum value (numbers, durations) min:"1024"
max Maximum value (numbers, durations) max:"65535"
pattern Regex pattern for strings pattern:"^[a-z]+$"
scheme Command separated list of schemes for *url.URL scheme:"http,https"
required Must be present and non-empty required:"true"
keyRequired Must be present (can be empty) keyRequired:"true"

Supported Types

  • Primitives: string, bool
  • Integers: int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64
  • Floats: float32, float64
  • Duration: time.Duration - uses Go format: "30s", "5m", "1h"
  • JSON: map[string]interface{} or structs with json tags
  • Pointers: All above types as pointers
  • Nested structs: Organize configuration hierarchically

Validation

Built-in Validators

type ServerConfig struct {
    Port       int           `key:"PORT" default:"8080" min:"1024" max:"65535"`
    MaxConns   int           `key:"MAX_CONNS" default:"100" min:"1" max:"10000"`
    LoadFactor float64       `key:"LOAD_FACTOR" default:"0.75" min:"0.0" max:"1.0"`
    Timeout    time.Duration `key:"TIMEOUT" default:"30s" min:"1s" max:"5m"`
    Username   string        `key:"USERNAME" pattern:"^[a-zA-Z0-9_]+$"`
}

Validation errors provide clear messages:

invalid value for PORT: below minimum 1024

Custom Types

Define custom types with validation using the building block architecture - compose simple, reusable components:

type APIKey string

type Config struct {
    APIKey APIKey `key:"API_KEY" required:"true"`
}

// Building block approach: parser + validators
apiKeyHandler := goconfig.NewCustomType(
    func(rawValue string) (APIKey, error) {
        return APIKey(rawValue), nil
    },
    func(value APIKey) error {
        if !strings.HasPrefix(string(value), "sk-") {
            return fmt.Errorf("API key must start with 'sk-'")
        }
        return nil
    },
)

err := goconfig.Load(context.Background(), &cfg,
    goconfig.WithCustomType[APIKey](apiKeyHandler),
)

The building block system lets you compose handlers:

  • NewCustomType - Start with parser and validators
  • AddValidators - Add validators to existing handlers
  • CastCustomType - Transform handlers for type aliases
  • NewStringEnumType - Specialized enum builder

πŸ“š Custom Types Guide | Validation Guide | Example

JSON Configuration

Load complex JSON structures from environment variables:

type ModelParams struct {
    Temperature float64 `json:"temperature"`
    MaxTokens   int     `json:"max_tokens"`
}

type Config struct {
    Params ModelParams `key:"MODEL_PARAMS"`
}
export MODEL_PARAMS='{"temperature":0.7,"max_tokens":1000}'

πŸ“š JSON Guide

Troubleshooting

If you see an error about parsing JSON when you are not expecting a JSON value, check that the type is recognized. The JSON handling for struct types catches various types (such as url.URL before I added support for it)

Documentation

Examples

Advanced Usage

Custom Key Stores

Read from sources other than environment variables:

// Composite store: try environment, then fall back to file
store := goconfig.CompositeStore(
    goconfig.EnvironmentKeyStore,
    fileKeyStore("/etc/myapp/config"),
)

err := goconfig.Load(context.Background(), &cfg,
    goconfig.WithKeyStore(store),
)

Supports AWS Secrets Manager, HashiCorp Vault, config files, and more.

πŸ“š Advanced Guide

Error Handling

err := goconfig.Load(context.Background(), &config)
if err != nil {
    // Check for specific errors
    if errors.Is(err, goconfig.ErrMissingConfigKey) {
        log.Fatal("Missing required environment variable")
    }

    log.Fatalf("Configuration error: %v", err)
}

Multiple errors are collected and reported together for easier debugging.

Testing

go test -v

Contributing

Contributions welcome! Please open an issue or pull request on GitHub.

License

MIT License - see LICENSE file for details.

Links

About

Helper to read config from environment.

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages