Options Reference

Complete reference for all configuration option functions

Comprehensive documentation of all option functions used to configure Config instances.

Option Type

type Option func(*Config) error

Options are functions that configure a Config instance during initialization. They are passed to New() or MustNew().

Environment Variable Expansion

All path-based options (WithFile, WithFileAs, WithConsul, WithConsulAs, WithFileDumper, WithFileDumperAs) support environment variable expansion in paths. This makes it easy to use different paths based on your environment.

Supported syntax:

  • ${VAR} - Braced variable name
  • $VAR - Simple variable name

Note: Shell-style defaults like ${VAR:-default} are NOT supported. Set defaults in your code before calling the option.

Examples:

// Environment-based Consul path
config.WithConsul("${APP_ENV}/service.yaml")
// When APP_ENV=production, expands to: "production/service.yaml"

// Config directory from environment
config.WithFile("${CONFIG_DIR}/app.yaml")
// When CONFIG_DIR=/etc/myapp, expands to: "/etc/myapp/app.yaml"

// Multiple variables
config.WithFile("${REGION}/${ENV}/settings.yaml")
// When REGION=us-west and ENV=staging, expands to: "us-west/staging/settings.yaml"

// Output directory
config.WithFileDumper("${LOG_DIR}/effective-config.yaml")
// When LOG_DIR=/var/log, expands to: "/var/log/effective-config.yaml"

Handling unset variables:

If an environment variable is not set, it expands to an empty string:

// If APP_ENV is not set:
config.WithConsul("${APP_ENV}/service.yaml")  // Expands to: "/service.yaml"

To provide defaults, set them in your code:

if os.Getenv("APP_ENV") == "" {
    os.Setenv("APP_ENV", "development")
}
config.WithConsul("${APP_ENV}/service.yaml")  // Uses "development" if not set

Source Options

Source options specify where configuration data comes from.

WithFile

func WithFile(path string) Option

Loads configuration from a file with automatic format detection based on extension.

Parameters:

  • path - Path to configuration file.

Supported extensions:

  • .json - JSON format.
  • .yaml, .yml - YAML format.
  • .toml - TOML format.

Example:

cfg := config.MustNew(
    config.WithFile("config.yaml"),
    config.WithFile("config.json"),
)

Error conditions:

  • File does not exist (error occurs during Load(), not initialization)
  • Extension not recognized

WithFileAs

func WithFileAs(path string, codecType codec.Type) Option

Loads configuration from a file with explicit format specification.

Parameters:

  • path - Path to configuration file.
  • codecType - Codec type like codec.TypeYAML or codec.TypeJSON.

Example:

cfg := config.MustNew(
    config.WithFileAs("config.txt", codec.TypeYAML),
    config.WithFileAs("settings.conf", codec.TypeJSON),
)

Use when: File extension doesn’t match its format.

WithEnv

func WithEnv(prefix string) Option

Loads configuration from environment variables with the given prefix.

Parameters:

  • prefix - Prefix to filter environment variables (e.g., “APP_”, “MYAPP_”)

Naming convention:

  • PREFIX_KEYkey
  • PREFIX_SECTION_KEYsection.key
  • PREFIX_A_B_Ca.b.c

Example:

cfg := config.MustNew(
    config.WithEnv("MYAPP_"),
)

// Environment: MYAPP_SERVER_PORT=8080
// Maps to: server.port = 8080

See also: Environment Variables Guide

WithConsul

func WithConsul(path string) Option

Loads configuration from HashiCorp Consul. The format is detected from the file extension.

Works without Consul: If CONSUL_HTTP_ADDR isn’t set, this option does nothing. This means you can run your app locally without Consul. When you deploy to production, just set the environment variable and Consul will be used.

Parameters:

  • path - Consul key path (format detected from extension)

Example:

cfg := config.MustNew(
    config.WithFile("config.yaml"),
    config.WithConsul("production/service.json"),  // Skipped in dev, used in prod
)

Environment variables:

  • CONSUL_HTTP_ADDR - Consul server address (required for Consul to work)
  • CONSUL_HTTP_TOKEN - Access token for authentication (optional)

WithConsulAs

func WithConsulAs(path string, codecType codec.Type) Option

Loads configuration from Consul with explicit format. Use this when the key path doesn’t have an extension.

Works without Consul: Like WithConsul, this option does nothing if CONSUL_HTTP_ADDR isn’t set. Your code works the same in dev and prod.

Parameters:

  • path - Consul key path
  • codecType - Codec type (like codec.TypeYAML or codec.TypeJSON)

Example:

cfg := config.MustNew(
    config.WithFile("config.yaml"),
    config.WithConsulAs("config/app", codec.TypeYAML),  // No extension in key
)

Environment variables:

  • CONSUL_HTTP_ADDR - Consul server address (required for Consul to work)
  • CONSUL_HTTP_TOKEN - Access token for authentication (optional)

WithContent

func WithContent(data []byte, codecType codec.Type) Option

Loads configuration from a byte slice.

Parameters:

  • data - Configuration data as bytes
  • codecType - Codec type for decoding

Example:

configData := []byte(`{"server": {"port": 8080}}`)
cfg := config.MustNew(
    config.WithContent(configData, codec.TypeJSON),
)

Use cases:

  • Testing
  • Dynamic configuration
  • Embedded configuration

WithSource

func WithSource(loader Source) Option

Adds a custom configuration source.

Parameters:

  • loader - Custom source implementing the Source interface

Source interface:

type Source interface {
    Load(ctx context.Context) (map[string]any, error)
}

Example:

type CustomSource struct{}

func (s *CustomSource) Load(ctx context.Context) (map[string]any, error) {
    return map[string]any{"key": "value"}, nil
}

cfg := config.MustNew(
    config.WithSource(&CustomSource{}),
)

Validation Options

Validation options enable configuration validation.

WithBinding

func WithBinding(v any) Option

Binds configuration to a Go struct and optionally validates it.

Parameters:

  • v - Pointer to struct to bind configuration to

Example:

type Config struct {
    Port int `config:"port"`
}

var cfg Config
config := config.MustNew(
    config.WithFile("config.yaml"),
    config.WithBinding(&cfg),
)

Validation: If the struct implements Validate() error, it will be called after binding.

Requirements:

  • Must pass a pointer to the struct
  • Struct fields must have config:"name" tags

See also: Struct Binding Guide

WithTag

func WithTag(tagName string) Option

Changes the struct tag name used for binding (default: “config”).

Parameters:

  • tagName - Tag name to use instead of “config”

Example:

type Config struct {
    Port int `yaml:"port"`
}

var cfg Config
config := config.MustNew(
    config.WithTag("yaml"),
    config.WithBinding(&cfg),
)

Use when: You want to reuse existing struct tags (e.g., json, yaml).

WithValidator

func WithValidator(fn func(map[string]any) error) Option

Registers a custom validation function for the configuration map.

Parameters:

  • fn - Validation function that receives the merged configuration

Example:

cfg := config.MustNew(
    config.WithFile("config.yaml"),
    config.WithValidator(func(data map[string]any) error {
        port, ok := data["port"].(int)
        if !ok || port <= 0 {
            return errors.New("port must be a positive integer")
        }
        return nil
    }),
)

Timing: Validation runs after sources are merged, before struct binding.

Multiple validators: You can register multiple validators; all will be executed.

WithJSONSchema

func WithJSONSchema(schema []byte) Option

Validates configuration against a JSON Schema.

Parameters:

  • schema - JSON Schema as bytes

Example:

schemaBytes, _ := os.ReadFile("schema.json")
cfg := config.MustNew(
    config.WithFile("config.yaml"),
    config.WithJSONSchema(schemaBytes),
)

Schema validation:

See also: Validation Guide

Dumper Options

Dumper options specify where to write configuration.

WithFileDumper

func WithFileDumper(path string) Option

Writes configuration to a file with automatic format detection.

Parameters:

  • path - Output file path (format detected from extension)

Example:

cfg := config.MustNew(
    config.WithFile("config.yaml"),
    config.WithEnv("APP_"),
    config.WithFileDumper("effective-config.yaml"),
)

cfg.Load(context.Background())
cfg.Dump(context.Background())  // Writes to effective-config.yaml

Default permissions: 0644 (owner read/write, group/others read)

WithFileDumperAs

func WithFileDumperAs(path string, codecType codec.Type) Option

Writes configuration to a file with explicit format specification.

Parameters:

  • path - Output file path
  • codecType - Codec type for encoding

Example:

cfg := config.MustNew(
    config.WithFile("config.yaml"),
    config.WithFileDumperAs("output.json", codec.TypeJSON),
)

WithDumper

func WithDumper(dumper Dumper) Option

Adds a custom configuration dumper.

Parameters:

  • dumper - Custom dumper implementing the Dumper interface

Dumper interface:

type Dumper interface {
    Dump(ctx context.Context, data map[string]any) error
}

Example:

type CustomDumper struct{}

func (d *CustomDumper) Dump(ctx context.Context, data map[string]any) error {
    // Write data somewhere
    return nil
}

cfg := config.MustNew(
    config.WithFile("config.yaml"),
    config.WithDumper(&CustomDumper{}),
)

Option Composition

Options are applied in the order they are passed to New() or MustNew():

cfg := config.MustNew(
    // 1. Load base config
    config.WithFile("config.yaml"),
    
    // 2. Load environment-specific config
    config.WithFile("config.prod.yaml"),
    
    // 3. Override with environment variables (highest priority)
    config.WithEnv("APP_"),
    
    // 4. Set up validation
    config.WithJSONSchema(schemaBytes),
    config.WithValidator(customValidation),
    
    // 5. Bind to struct
    config.WithBinding(&appConfig),
    
    // 6. Set up dumper
    config.WithFileDumper("effective-config.yaml"),
)

Source Precedence

When multiple sources are configured, later sources override earlier ones:

cfg := config.MustNew(
    config.WithFile("config.yaml"),      // Priority 1 (lowest)
    config.WithFile("config.prod.yaml"), // Priority 2
    config.WithEnv("APP_"),              // Priority 3 (highest)
)

Validation Order

Validation happens in this sequence during Load():

  1. Load and merge all sources
  2. JSON Schema validation (if configured)
  3. Custom validation functions (if configured)
  4. Struct binding (if configured)
  5. Struct Validate() method (if implemented)

Common Patterns

Pattern 1: Basic Configuration

cfg := config.MustNew(
    config.WithFile("config.yaml"),
)

Pattern 2: Environment Override

cfg := config.MustNew(
    config.WithFile("config.yaml"),
    config.WithEnv("APP_"),
)

Pattern 3: Multi-Environment

env := os.Getenv("APP_ENV")
cfg := config.MustNew(
    config.WithFile("config.yaml"),
    config.WithFile("config."+env+".yaml"),
    config.WithEnv("APP_"),
)

Pattern 4: With Validation

var appConfig AppConfig
cfg := config.MustNew(
    config.WithFile("config.yaml"),
    config.WithEnv("APP_"),
    config.WithBinding(&appConfig),
)

Pattern 5: Production Setup

var appConfig AppConfig
schemaBytes, _ := os.ReadFile("schema.json")

cfg := config.MustNew(
    config.WithFile("config.yaml"),
    config.WithEnv("APP_"),
    config.WithJSONSchema(schemaBytes),
    config.WithBinding(&appConfig),
    config.WithFileDumper("effective-config.yaml"),
)

Next Steps