configloader

package module
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Feb 8, 2026 License: MIT Imports: 15 Imported by: 0

README

configloader

Go Reference Go Report Card codecov

Load configuration from environment variables into Go structs.

type Config struct {
    Host string
    Port int
}

var cfg Config
if err := configloader.Load(&cfg); err != nil {
    log.Fatal(err)
}
// Reads HOST and PORT from environment

Working with Errors

No more frustrating debug cycles where you fix one missing environment variable only to discover another.

Unlike libraries that fail on the first error, configloader validates your entire configuration upfront and reports every issue in a single, clear error message:

failed to load main.Config:
  error processing field Host (string): environment variable HOST not found
  error processing field Port (int): strconv.ParseInt: parsing "abc": invalid syntax
  error processing field Database.URL (*url.URL): environment variable DATABASE_URL not found
  error processing field Database.MaxConns (int): environment variable DATABASE_MAX_CONNS not found

Errors returned by Load() implement the standard library's multi-error interface (Unwrap() []error), allowing you to programmatically inspect individual errors:

if err := configloader.Load(&cfg); err != nil {
    // Print the complete error message
    fmt.Println(err)
    
    // Or inspect individual errors using errors.As
    var loadErr *configloader.ConfigLoadError
    if errors.As(err, &loadErr) {
        for _, e := range loadErr.Errors {
            var missingErr configloader.MissingEnvError
            if errors.As(e, &missingErr) {
                fmt.Printf("Missing required variable: %s\n", missingErr.Key)
            }
        }
    }
}

Installation

go get github.com/hadrienk/configloader

Requires Go 1.23+.

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Load

func Load(value any, opts ...Option) error

Load populates a struct's fields with values from environment variables. It takes a pointer to a struct and optional configuration options.

Each struct field's name is converted to SCREAMING_SNAKE_CASE to determine the environment variable name. For example:

  • Field "ServerPort" looks for "SERVER_PORT"
  • Field "DatabaseURL" looks for "DATABASE_URL"
  • Nested field "Database.Password" looks for "DATABASE_PASSWORD"

Supported field types out of the box:

  • Basic types: string, bool, int*, uint*, float*
  • time.Duration, time.Time (RFC3339 format)
  • net.IP, *net.IPNet (CIDR)
  • *url.URL, *regexp.Regexp
  • json.RawMessage
  • []byte (base64 encoded)
  • Slices of any supported type (comma-separated values)

Features:

  • Custom type support via WithTypeHandler
  • Default values via struct tags: `default:"value"`
  • Custom env names via struct tags: `env:"CUSTOM_NAME"`
  • Optional prefix for all env vars: WithPrefix("APP")
  • Nested struct support
  • Pointer fields are automatically initialized

Example usage:

type Config struct {
    Port        int           `default:"8080"`
    Host        string        `env:"SERVICE_HOST"`
    Timeout     time.Duration
    Database struct {
        URL      string
        Password string
    }
}

var cfg Config
err := configloader.Load(&cfg,
    WithPrefix("APP"),
    WithNameTag("env"),
    WithDefaultTag("default"),
)

The above will look for these environment variables:

  • APP_PORT (default: "8080")
  • SERVICE_HOST (custom name via tag)
  • APP_TIMEOUT
  • APP_DATABASE_URL
  • APP_DATABASE_PASSWORD

Returns an error if:

  • The value is not a pointer to a struct
  • Required environment variables are missing
  • Type conversion fails for any field
  • Any field has an unsupported type

Types

type ConfigLoadError

type ConfigLoadError struct {
	Value  reflect.Type
	Errors []error
}

ConfigLoadError represents the errors that occurred during config loading.

func (*ConfigLoadError) Add

func (e *ConfigLoadError) Add(err error)

Add appends an error to the ConfigLoadError.

func (*ConfigLoadError) Error

func (e *ConfigLoadError) Error() string

func (*ConfigLoadError) Unwrap

func (e *ConfigLoadError) Unwrap() []error

type FieldError

type FieldError struct {
	Err error
	// contains filtered or unexported fields
}

FieldError represents an error that occurred while processing a specific field.

func (FieldError) Error

func (e FieldError) Error() string

func (*FieldError) Last added in v1.1.0

func (f *FieldError) Last() reflect.StructField

Last returns the last field in the path.

func (*FieldError) Names added in v1.1.0

func (f *FieldError) Names() (names []string)

Names returns the names of all fields in the path.

func (*FieldError) String added in v1.1.0

func (f *FieldError) String() string

func (FieldError) Unwrap

func (e FieldError) Unwrap() error

type MissingEnvError

type MissingEnvError struct {
	Key      string
	Optional bool
}

MissingEnvError represents an error when a required environment variable is not found.

func (MissingEnvError) Error

func (e MissingEnvError) Error() string

type Option

type Option func(*loader)

Option is a functional option for configuring a loader.

func WithDefaultTag

func WithDefaultTag(tag string) Option

WithDefaultTag sets the struct tag used for specifying default values. If an environment variable is not found, the value of this tag will be used instead.

Example:

type Config struct {
    Port int `default:"8080"`  // Will use 8080 if PORT is not set
}
configloader.Load(&cfg, WithDefaultTag("default"))

func WithEnv

func WithEnv(env func(string) (string, bool)) Option

WithEnv sets a custom function for looking up environment variables. This is primarily useful for testing or when environment variables need to be sourced from somewhere other than os.LookupEnv.

The function should return the value and a boolean indicating whether the variable was found, similar to os.LookupEnv.

func WithEnvTag

func WithEnvTag(tag string) Option

WithEnvTag sets the struct tag used to completely override the environment variable name for a field. When a field has this tag, its value is used as-is for the environment variable name, bypassing all other name construction rules including prefixes and path building.

Example with WithEnvTag("env"):

type Config struct {
    Database struct {
        // Despite nesting, looks directly for "DB_HOST"
        Host string `env:"DB_HOST"`
    }
}
configloader.Load(&cfg)

Example showing prefix is ignored with env tag:

type Config struct {
    Database struct {
        // Still only looks for "DB_HOST", prefix is not applied
        Host string `env:"DB_HOST"`
    }
}
configloader.Load(&cfg, WithPrefix("APP"))

func WithNameTag

func WithNameTag(tag string) Option

WithNameTag sets the struct tag used to override a field's name in the environment variable path. The tag value replaces just the field's name segment while still following the normal path construction rules (prefix + path + name).

Example with WithNameTag("name"):

type Config struct {
    Database struct {
        Host string `name:"HOSTNAME"` // Looks for DATABASE_HOSTNAME
    }
}
configloader.Load(&cfg)

Example with both prefix and name tag:

type Config struct {
    Database struct {
        Host string `name:"HOSTNAME"` // Looks for APP_DATABASE_HOSTNAME
    }
}
configloader.Load(&cfg, WithPrefix("APP"))

func WithOptionalTag added in v1.1.0

func WithOptionalTag(tag string) Option

WithOptionalTag configures the struct tag name for marking fields as optional. Optional fields will not return an error if their environment variable is missing and no default value is provided. They remain at their zero value instead.

The tag value can be:

  • Empty string for optional: `optional:""`
  • Explicit boolean: `optional:"true"` or `optional:"false"`

If a field has both optional and default tags, the default value is used when the environment variable is missing.

Example:

type Config struct {
    Required    string              // Error if REQUIRED not set
    Optional    string `optional:""` // OK if OPTIONAL not set, remains ""
    OptionalURL *url.URL `optional:"true"` // OK if not set, remains nil
    WithDefault string `optional:"" default:"fallback"` // Uses fallback
}

err := configloader.Load(&cfg)

func WithPrefix

func WithPrefix(prefix string) Option

WithPrefix sets a prefix that will be prepended to all environment variable names. The prefix and field name will be joined with an underscore.

Example:

type Config struct {
    Port int  // Will look for "APP_PORT" environment variable
}
configloader.Load(&cfg, WithPrefix("APP"))

func WithTypeHandler

func WithTypeHandler[T any](f func(string) (T, error)) Option

WithTypeHandler registers a custom type conversion function for a specific type T. The function should convert a string environment value to type T, returning an error if the conversion fails.

Example:

configloader.Load(&cfg, WithTypeHandler(func(s string) (time.Duration, error) {
    return time.ParseDuration(s)
}))

type UnsupportedTypeError

type UnsupportedTypeError struct {
	Type reflect.Type
}

UnsupportedTypeError represents an error when trying to process a field with an unsupported type.

func (UnsupportedTypeError) Error

func (e UnsupportedTypeError) Error() string

Jump to

Keyboard shortcuts

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