configure

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Sep 5, 2025 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package configure provides utilities for applying functional options to objects.

Package configure provides a robust, type-safe, and flexible implementation of the Functional Options Pattern for Go. It is designed to handle a wide range of configuration scenarios, from simple object initialization to complex, multi-stage product compilation.

Core Concepts

The package is built around a few core ideas:

  • **Type-Safe Application**: For the highest performance and compile-time safety, use the `Apply` and `ApplyE` functions. They are ideal when all options are of the same, known type.

    // Example of simple, type-safe configuration: type Server struct { Port int Host string } type Option func(*Server) func WithPort(p int) Option { return func(s *Server) { s.Port = p } } func WithHost(h string) Option { return func(s *Server) { s.Host = h } }

    server := &Server{} configure.Apply(server, []Option{ WithPort(8080), WithHost("localhost"), })

  • **Flexible Application**: When you need to handle a mix of different option types, use `ApplyAny`. This function uses type assertions to provide flexibility, at the cost of compile-time safety and a minor performance overhead.

    opts := []any{ WithPort(8080), func(s *Server) { s.Host = "example.com" }, // A raw function } server, err := configure.New[Server](opts...)

  • **Stateful Builder**: For scenarios where options are collected progressively from different parts of your application, use the `Builder`. It provides a fluent, chainable API.

    builder := configure.NewBuilder[Server](). Add(WithPort(443)). AddWhen(isProduction, WithHost("prod.server.com"))

    server, err := builder.Build()

  • **Compilation**: For the advanced use case of transforming a configuration object `C` into a final product `P`, use the top-level `Compile` function. This separates the configuration logic from the product creation logic.

    // Example: Using a `ClientConfig` to create an `*http.Client` type ClientConfig struct { Timeout time.Duration } factory := func(c *ClientConfig) (*http.Client, error) { return &http.Client{Timeout: c.Timeout}, nil }

    configBuilder := configure.NewBuilder[ClientConfig](). Add(func(c *ClientConfig) { c.Timeout = 20 * time.Second })

    httpClient, err := configure.Compile(configBuilder, factory)

By combining these tools, developers can choose the right approach for their specific needs, ensuring code remains clean, maintainable, and robust.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Apply

func Apply[T any, O FuncOption[T]](target *T, opts []O) *T

Apply applies a slice of options to the target. It is the core, high-performance function for applying a homogeneous set of type-safe options. Its generic constraint allows for custom-defined option types, such as `type MyOption func(*T)`.

For handling mixed option types, see ApplyAny.

func ApplyAny

func ApplyAny[T any](target *T, opts []any) (*T, error)

ApplyAny applies a slice of options of various types (any). This function provides flexibility by using reflection to handle heterogeneous options, at the cost of compile-time type safety and a minor performance overhead.

For type-safe, high-performance application, see Apply or ApplyE.

func ApplyAnyWith

func ApplyAnyWith[T any](target *T, opts ...any) (*T, error)

ApplyAnyWith is the variadic convenience wrapper for ApplyAny.

func ApplyE

func ApplyE[T any, O FuncOptionE[T]](target *T, opts []O) (*T, error)

ApplyE applies a slice of error-returning options to the target. It is the core, high-performance function for applying a homogeneous set of type-safe, error-returning options. Its generic constraint allows for custom-defined option types.

For handling mixed option types, see ApplyAny.

func ApplyWith

func ApplyWith[T any](target *T, opts ...Option[T]) *T

ApplyWith is the variadic convenience wrapper for Apply.

func ApplyWithE

func ApplyWithE[T any](target *T, opts ...OptionE[T]) (*T, error)

ApplyWithE is the variadic convenience wrapper for ApplyE.

func Compile

func Compile[C any, P any](builder *Builder[C], factory func(c *C) (*P, error)) (*P, error)

Compile creates a final product `P` by first building a configuration `C` using the provided builder, and then passing the result to a factory function. This is the primary top-level function for the Config -> Product workflow, ensuring a clean separation between configuration and compilation.

func IsConfigError

func IsConfigError(err error) bool

IsConfigError checks if the given error is a *ConfigError.

func IsEmptyTargetValueError

func IsEmptyTargetValueError(err error) bool

IsEmptyTargetValueError checks if the error is a ConfigError with the code ErrEmptyTargetValue.

func IsExecutionFailedError

func IsExecutionFailedError(err error) bool

IsExecutionFailedError checks if the error is a ConfigError with the code ErrExecutionFailed.

func IsUnsupportedTypeError

func IsUnsupportedTypeError(err error) bool

IsUnsupportedTypeError checks if the error is a ConfigError with the code ErrUnsupportedType.

func New

func New[T any](opts ...any) (*T, error)

New creates a new instance of T, applies the given options, and returns it. It is a convenient top-level constructor for simple object creation where the configuration type and the product type are the same.

It uses ApplyAnyWith for maximum flexibility in accepting options.

Types

type Applier

type Applier[T any] interface {
	Apply(*T)
}

Applier is an interface for types that can apply a configuration to an object. It provides an extension point for ApplyAny, allowing custom types to be used as options without reflection.

type ApplierE

type ApplierE[T any] interface {
	Apply(*T) error
}

ApplierE is an interface for types that can apply a configuration and return an error. It provides an extension point for ApplyAny, allowing custom types to be used as options without reflection.

type Builder

type Builder[C any] struct {
	// contains filtered or unexported fields
}

Builder provides a fluent interface for collecting and applying options. It is ideal for scenarios where configuration options are gathered progressively from different parts of an application.

The generic type C represents the configuration type being built, and is expected to be a struct type. Using a pointer type for C is not recommended as it can lead to unexpected behavior.

func NewBuilder

func NewBuilder[C any]() *Builder[C]

NewBuilder creates a new, empty configuration builder.

func (*Builder[C]) Add

func (b *Builder[C]) Add(opts ...any) *Builder[C]

Add adds one or more options to the builder. It supports a fluent, chainable API.

func (*Builder[C]) AddWhen

func (b *Builder[C]) AddWhen(condition bool, opt any) *Builder[C]

AddWhen conditionally adds an option to the builder if the condition is true. It supports a fluent, chainable API.

func (*Builder[C]) Apply

func (b *Builder[C]) Apply(target *C) error

Apply implements the ApplierE interface. This allows a Builder instance to be passed directly as an option to other functions like New or ApplyAny, acting as a "super option".

func (*Builder[C]) ApplyTo

func (b *Builder[C]) ApplyTo(target *C) (*C, error)

ApplyTo applies all collected options to an existing target object.

func (*Builder[C]) Build

func (b *Builder[C]) Build() (*C, error)

Build creates a new, zero-value instance of the configuration object C and applies all collected options to it. The resulting object can then be used directly or passed to a factory.

type ConfigError

type ConfigError struct {
	// Code is the category of the error.
	Code ErrorCode
	// TypeString is the string representation of the option's type.
	TypeString string
	// Err is the underlying error, if any.
	Err error
}

ConfigError is a custom error type for the configure package. It wraps an original error while providing additional context, such as the type of option that caused the failure and a specific error code.

func (*ConfigError) Error

func (e *ConfigError) Error() string

Error implements the standard error interface.

func (*ConfigError) Unwrap

func (e *ConfigError) Unwrap() error

Unwrap makes ConfigError compatible with the standard library's errors.Is and errors.As functions, allowing for proper error chain inspection.

type ErrorCode

type ErrorCode int

ErrorCode defines the specific category of a configuration error.

const (
	// ErrUnsupportedType indicates that an option's type is not supported by
	// the ApplyAny function.
	ErrUnsupportedType ErrorCode = iota

	// ErrExecutionFailed indicates that an option function returned an error
	// during its execution.
	ErrExecutionFailed

	// ErrEmptyTargetValue indicates that a nil pointer was passed as the target
	// for configuration.
	ErrEmptyTargetValue
)

Error codes for specific configuration failures.

type FuncOption

type FuncOption[T any] interface {
	~func(*T)
}

FuncOption is a generic constraint that permits any function type whose underlying type is func(*T). This enables the top-level Apply function to accept custom-defined option types, such as `type MyOption func(*T)`.

type FuncOptionAny

type FuncOptionAny[T any] interface {
	FuncOptionE[T] | FuncOption[T] | any
}

FuncOptionAny is a generic constraint that permits any function type whose underlying type is either func(*T) or func(*T) error. This provides a convenient way to create functions that can accept both error-returning and non-error-returning function options.

type FuncOptionE

type FuncOptionE[T any] interface {
	~func(*T) error
}

FuncOptionE is a generic constraint that permits any function type whose underlying type is func(*T) error. This enables the top-level ApplyE function to accept custom-defined, error-returning option types.

type Option

type Option[T any] func(*T)

Option represents a function that configures an object of type T. It is the primary, non-error-returning type for the Functional Options Pattern.

func OptionSet

func OptionSet[T any](opts ...Option[T]) Option[T]

OptionSet bundles multiple options into a single option. This allows for creating reusable and modular sets of configurations.

func (Option[T]) Apply

func (o Option[T]) Apply(target *T)

Apply implements the Applier[T] interface, allowing an Option[T] to be used as a flexible option type with functions like ApplyAny.

type OptionE

type OptionE[T any] func(*T) error

OptionE represents a function that configures an object of type T and may return an error. The 'E' suffix is a convention for "Error".

func OptionSetE

func OptionSetE[T any](opts ...OptionE[T]) OptionE[T]

OptionSetE bundles multiple error-returning options into a single option. If any option in the set returns an error, the application stops and the error is returned.

func WithValidation

func WithValidation[T any](validator func(*T) error) OptionE[T]

WithValidation creates an option that validates the target object. If the validator function returns an error, the configuration process will stop.

func (OptionE[T]) Apply

func (o OptionE[T]) Apply(target *T) error

Apply implements the ApplierE[T] interface, allowing an OptionE[T] to be used as a flexible option type with functions like ApplyAny.

Jump to

Keyboard shortcuts

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