gcfg

package module
v0.0.13 Latest Latest
Warning

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

Go to latest
Published: Oct 8, 2025 License: MIT Imports: 14 Imported by: 1

README

gcfg

A flexible configuration management system for Go that supports reading from multiple providers and binding to user-defined types.

Features

  • Multiple Providers: Support for environment variables, JSON files, dotenv files, and more
  • Flexible API: Easy-to-use interface for loading and binding configuration
  • Extensible: Create custom providers by implementing the Provider interface
  • Hierarchical: Support for nested configuration using dot notation (e.g., database.host)
  • Merge Strategy: Later providers override earlier ones for flexible configuration layering

Installation

go get github.com/ahmedkamalio/gcfg

Quick Start

Basic Usage
package main

import (
	"fmt"
	"github.com/ahmedkamalio/gcfg"
)

type AppConfig struct {
	Database struct {
		Host string
		Port int
	}
	Server struct {
		Host string
		Port int
	}
}

func main() {
	// Create config (environment provider is registered by default).
	config := gcfg.New()

	// Load configuration
	if err := config.Load(); err != nil {
		panic(err)
	}

	// Bind to your config struct
	var appCfg AppConfig
	if err := config.Bind(&appCfg); err != nil {
		panic(err)
	}

	fmt.Printf("Server: %s:%d\n", appCfg.Server.Host, appCfg.Server.Port)
}
Using JSON Configuration
package main

import (
	"github.com/ahmedkamalio/gcfg"
)

func main() {
	// Initialize config with JSON provider
	config := gcfg.New(
		gcfg.NewJSONProvider(
			gcfg.WithJSONFilePath("config.json"),
		),
	)

	// Load and bind as shown above
	// ...
}

Example config.json:

{
  "database": {
    "host": "localhost",
    "port": 5432
  },
  "server": {
    "host": "0.0.0.0",
    "port": 8080
  }
}
Using environment variables

Set environment variables:

export DATABASE_HOST=localhost
export DATABASE_PORT=5432
export SERVER_HOST=0.0.0.0
export SERVER_PORT=8080

Then in your Go code:

config := gcfg.New(gcfg.NewEnvProvider())
Using .env files
package main

import (
	"github.com/ahmedkamalio/gcfg"
)

func main() {
	// Initialize config with dotenv provider
	config := gcfg.New(
		gcfg.NewDotEnvProvider(), // defaults to ".env"
	)

	// Load and bind as shown above
	// ...
}

Example .env file:

DATABASE_HOST=localhost
DATABASE_PORT=5432
SERVER_HOST=0.0.0.0
SERVER_PORT=8080
Combining Multiple Providers

You can combine multiple providers, with later providers overriding earlier ones:

config := gcfg.New(
// Default values from JSON
gcfg.NewJSONProvider(gcfg.WithJSONFilePath("config.json")),
// Override with environment variables
gcfg.NewEnvProvider(),
// Override with .env file
gcfg.NewDotEnvProvider(),
)

API Reference

Config
New(providers ...Provider) *Config

Creates a new configuration instance with the given providers. If no EnvProvider is provided, one will be added automatically.

SetDefault(key string, value any)

Sets a default value for the specified key in the configuration. Supports hierarchical paths like "database.host"

SetDefaults(values any) error

Sets default configuration values from a struct or map. Returns an error if the input is invalid or nil.

Load() error

Loads configuration from all providers, merging values. Later providers override earlier ones.

Bind(dest any) error

Binds the loaded configuration to a Go struct using reflection.

Get(key string) any

Retrieves a configuration value by key (supports hierarchical paths like "database.host").

Values() map[string]any

Returns all configuration values as a map.

Providers
Provider interface
type Provider interface {
    Name() string
    Load() (map[string]any, error)
}
Built-in Providers
  • NewEnvProvider() - Loads from environment variables
  • NewJSONProvider(options ...JSONProviderOption) - Loads from JSON files
  • NewDotEnvProvider() - Loads from dotenv files
Custom Providers
type CustomProvider struct{}

func (c *CustomProvider) Name() string {
    return "custom"
}

func (c *CustomProvider) Load() (map[string]any, error) {
    // Load configuration from your custom source
    return map[string]any{
        "my.setting": "value",
    }, nil
}

// Use it
config := gcfg.New(&CustomProvider{})

Examples

See the examples/ directory for complete examples:

Error Handling

All operations that can fail return errors that should be handled appropriately:

config := gcfg.New(gcfg.NewJSONProvider(gcfg.WithJSONFilePath("config.json")))
if err := config.Load(); err != nil {
    log.Fatalf("Failed to load config: %v", err)
}

var appCfg AppConfig
if err := config.Bind(&appCfg); err != nil {
    log.Fatalf("Failed to bind config: %v", err)
}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License.

Documentation

Overview

Package gcfg provides a flexible configuration management system that supports reading from multiple providers and binding to user-defined types.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrDotEnvFilePathNotSet indicates that the .env file path is not configured.
	ErrDotEnvFilePathNotSet = errors.New(".env file path is not set")
	// ErrDotEnvFileReadFailed indicates failure to read the .env file.
	ErrDotEnvFileReadFailed = errors.New("failed to read .env file")
	// ErrDotEnvParseFailed indicates failure to parse the .env file content.
	ErrDotEnvParseFailed = errors.New("failed to parse .env file")
	// ErrSetEnv indicates a failure call to os.Setenv().
	ErrSetEnv = errors.New("failed to set os env")
)
View Source
var (
	// ErrProviderLoadFailed indicates failure to load configuration from a provider.
	ErrProviderLoadFailed = errors.New("failed to load from provider")

	// ErrExtensionPreLoadHookFailed indicates a failure while executing the pre-load hook of an extension.
	ErrExtensionPreLoadHookFailed = errors.New("failed to execute extension pre-load hook")

	// ErrExtensionPostLoadHookFailed indicates a failure when executing the post-load hook of an extension.
	ErrExtensionPostLoadHookFailed = errors.New("failed to execute extension post-load hook")

	// ErrNilValues is returned when a nil value is provided where non-nil input is required.
	ErrNilValues = errors.New("values cannot be nil")
)
View Source
var (
	// ErrJSONFilePathNotSet indicates that the JSON file path is not configured.
	ErrJSONFilePathNotSet = errors.New("JSON file path is not set")
	// ErrJSONFileReadFailed indicates failure to read the JSON config file.
	ErrJSONFileReadFailed = errors.New("failed to read JSON config file")
	// ErrJSONDecodeFailed indicates failure to decode JSON content.
	ErrJSONDecodeFailed = errors.New("failed to decode JSON")
)

Functions

This section is empty.

Types

type BindOption added in v0.0.11

type BindOption func(*BindOptions)

BindOption is a functional option for configuring Bind behavior by modifying BindOptions.

func WithValidate added in v0.0.11

func WithValidate(validate bool) BindOption

WithValidate sets the validation flag in the BindOptions.

type BindOptions added in v0.0.11

type BindOptions struct {
	// contains filtered or unexported fields
}

BindOptions defines options for binding configuration data to a struct.

type Config

type Config struct {
	// contains filtered or unexported fields
}

Config represents the configuration loaded from various providers.

func New

func New(providers ...Provider) *Config

New creates a new config instance with given providers.

func (*Config) Bind

func (c *Config) Bind(dest any, options ...BindOption) error

Bind binds the configuration to the provided struct.

func (*Config) Find added in v0.0.7

func (c *Config) Find(key string) (value any, exist bool)

Find searches for and retrieves a configuration value by key. Supports hierarchical paths like "database.host".

func (*Config) Get

func (c *Config) Get(key string) any

Get retrieves a configuration value by key. Supports hierarchical paths like "database.host".

func (*Config) Load

func (c *Config) Load() error

Load loads configuration from all registered providers and applies pre/post-load hooks defined by extensions.

Returns an error if any provider or extension hook fails during the loading process.

func (*Config) LoadWithContext added in v0.0.6

func (c *Config) LoadWithContext(ctx context.Context) error

LoadWithContext loads configuration with the provided context, executing pre-load and post-load hooks for extensions.

func (*Config) Set added in v0.0.7

func (c *Config) Set(key string, value any)

Set sets a value for the specified key in the configuration, overriding any existing value. It creates nested maps if they do not exist.

func (*Config) SetDefault

func (c *Config) SetDefault(key string, value any)

SetDefault sets a default value for the specified key in the configuration. It creates nested maps if they do not exist, but does not override existing values.

func (*Config) SetDefaults

func (c *Config) SetDefaults(values any) error

SetDefaults sets default configuration values from a struct or map without overriding existing values. Returns an error if the input is invalid or nil.

func (*Config) Values

func (c *Config) Values() map[string]any

Values returns the configuration values.

func (*Config) WithExtensions added in v0.0.6

func (c *Config) WithExtensions(extensions ...Extension) *Config

WithExtensions appends one or more extensions to the configuration and returns the updated Config instance.

type DotEnvOption

type DotEnvOption func(*DotEnvProvider)

DotEnvOption is a function that configures a DotEnvProvider.

func WithDotEnvFileAppendToOSEnv added in v0.0.5

func WithDotEnvFileAppendToOSEnv(appendToOSEnv bool) DotEnvOption

WithDotEnvFileAppendToOSEnv sets the flag to append variables from the .env file to OS's env vars.

Default: true.

func WithDotEnvFileFS

func WithDotEnvFileFS(fs fs.FS) DotEnvOption

WithDotEnvFileFS sets the fs of which to read the .env file from.

Default: sysfs.SysFS.

func WithDotEnvFileNotFoundPanic added in v0.0.5

func WithDotEnvFileNotFoundPanic(panicIfNotFound bool) DotEnvOption

WithDotEnvFileNotFoundPanic sets the flag to panic of the .env file is not found.

Default: true.

func WithDotEnvFilePath

func WithDotEnvFilePath(filePath string) DotEnvOption

WithDotEnvFilePath sets the .env file path.

func WithDotEnvNormalizeVarNames

func WithDotEnvNormalizeVarNames(normalized bool) DotEnvOption

WithDotEnvNormalizeVarNames sets a flag to normalize variable names. If set to true, all variable names are converted from snake_case to lowercase identifier (snake case without underscores). This is useful to access environment variable names like "DATABASE_URL" with the key "DatabaseUrl".

Note: Variables can still be accessed using the original name, e.g., "database_url" -> "database_url", this only adds an alternative name and will NOT override the original names.

Default: true.

func WithDotEnvSeparator

func WithDotEnvSeparator(sep string) DotEnvOption

WithDotEnvSeparator sets the separator for nested map values. Given a sep=__ variables like DATABASE__URL become database.url in the resulting map.

type DotEnvProvider

type DotEnvProvider struct {
	*providers.FSProvider
	*EnvProvider
	// contains filtered or unexported fields
}

DotEnvProvider reads configuration from .env file.

func NewDotEnvProvider

func NewDotEnvProvider(opts ...DotEnvOption) *DotEnvProvider

NewDotEnvProvider creates .env provider with options.

func (*DotEnvProvider) Load

func (p *DotEnvProvider) Load() (map[string]any, error)

Load implements the Provider interface.

func (*DotEnvProvider) Name

func (p *DotEnvProvider) Name() string

Name implements the Provider interface.

type EnvOption

type EnvOption func(*EnvProvider)

EnvOption is a function that configures an EnvProvider.

func WithEnvNormalizeVarNames

func WithEnvNormalizeVarNames(normalized bool) EnvOption

WithEnvNormalizeVarNames sets a flag to normalize variable names. If set to true, all variable names are converted from snake_case to lowercase identifier (snake case without underscores). This is useful to access environment variable names like "DATABASE_URL" with the key "DatabaseUrl".

Note: Variables can still be accessed using the original name, e.g., "database_url" -> "database_url", this only adds an alternative name and will NOT override the original names.

Default: true.

func WithEnvPrefix

func WithEnvPrefix(prefix string) EnvOption

WithEnvPrefix sets the environment variable prefix. Only variables starting with this prefix are included, and the prefix is removed from the key (e.g., "APP_" prefix, "APP_HOST" -> "HOST").

func WithEnvSeparator

func WithEnvSeparator(sep string) EnvOption

WithEnvSeparator sets the separator for nested map values. Given a sep=__ variables like DATABASE__URL become database.url in the resulting map.

type EnvProvider

type EnvProvider struct {
	// contains filtered or unexported fields
}

EnvProvider reads configuration from environment variables.

func NewEnvProvider

func NewEnvProvider(opts ...EnvOption) *EnvProvider

NewEnvProvider creates an environment variable provider with options.

func (*EnvProvider) Load

func (p *EnvProvider) Load() (map[string]any, error)

Load implements the Provider interface.

func (*EnvProvider) Name

func (p *EnvProvider) Name() string

Name implements the Provider interface.

type Extension added in v0.0.6

type Extension interface {
	Name() string
	PreLoad(ctx context.Context, cfg *Config) error
	PostLoad(ctx context.Context, cfg *Config) error
}

Extension defines an interface for executing actions during the configuration loading process. The Name method is used to identify the extension by name. The PreLoad method is invoked prior to the main configuration loading phase. The PostLoad method is invoked after the main configuration loading phase.

type JSONOption

type JSONOption func(*JSONProvider)

JSONOption is a function that configures a JSONProvider.

func WithJSONFileFS

func WithJSONFileFS(fs fs.FS) JSONOption

WithJSONFileFS sets the fs of which to read the JSON file from.

Default: sysfs.SysFS.

func WithJSONFilePath

func WithJSONFilePath(filePath string) JSONOption

WithJSONFilePath sets the JSON file path.

type JSONProvider

type JSONProvider struct {
	*providers.FSProvider
	// contains filtered or unexported fields
}

JSONProvider reads configuration from a JSON file.

func NewJSONProvider

func NewJSONProvider(opts ...JSONOption) *JSONProvider

NewJSONProvider creates a new file provider.

func (*JSONProvider) Load

func (p *JSONProvider) Load() (map[string]any, error)

Load implements the Provider interface.

func (*JSONProvider) Name

func (p *JSONProvider) Name() string

Name implements the Provider interface.

type Provider

type Provider interface {
	Name() string
	// Load reads configuration from the source and returns it as a map.
	// Keys should be hierarchical paths (e.g., "database.host").
	Load() (map[string]any, error)
}

Provider defines the interface for configuration providers. Implement this interface to create custom providers like env, json, yml, etc.

Directories

Path Synopsis
internal
dotenv
Package dotenv provides functionality for parsing dotenv-style configuration files.
Package dotenv provides functionality for parsing dotenv-style configuration files.
env
Package env provides utilities for parsing environment variables into nested Go data structures.
Package env provides utilities for parsing environment variables into nested Go data structures.
maps
Package maps provides utilities for deep binding and merging of maps into Go data structures.
Package maps provides utilities for deep binding and merging of maps into Go data structures.
providers
Package providers implements a base FS-based configuration provider.
Package providers implements a base FS-based configuration provider.
reflection
Package reflection provides utilities for working with Go's reflection system.
Package reflection provides utilities for working with Go's reflection system.
sysfs
Package sysfs provides a file system implementation that ensures safe file operations.
Package sysfs provides a file system implementation that ensures safe file operations.

Jump to

Keyboard shortcuts

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