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 ¶
- func Apply[T any, O FuncOption[T]](target *T, opts []O) *T
- func ApplyAny[T any](target *T, opts []any) (*T, error)
- func ApplyAnyWith[T any](target *T, opts ...any) (*T, error)
- func ApplyE[T any, O FuncOptionE[T]](target *T, opts []O) (*T, error)
- func ApplyWith[T any](target *T, opts ...Option[T]) *T
- func ApplyWithE[T any](target *T, opts ...OptionE[T]) (*T, error)
- func Compile[C any, P any](builder *Builder[C], factory func(c *C) (*P, error)) (*P, error)
- func IsConfigError(err error) bool
- func IsEmptyTargetValueError(err error) bool
- func IsExecutionFailedError(err error) bool
- func IsUnsupportedTypeError(err error) bool
- func New[T any](opts ...any) (*T, error)
- type Applier
- type ApplierE
- type Builder
- type ConfigError
- type ErrorCode
- type FuncOption
- type FuncOptionAny
- type FuncOptionE
- type Option
- type OptionE
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 ¶
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 ¶
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 ApplyWithE ¶
ApplyWithE is the variadic convenience wrapper for ApplyE.
func Compile ¶
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 ¶
IsConfigError checks if the given error is a *ConfigError.
func IsEmptyTargetValueError ¶
IsEmptyTargetValueError checks if the error is a ConfigError with the code ErrEmptyTargetValue.
func IsExecutionFailedError ¶
IsExecutionFailedError checks if the error is a ConfigError with the code ErrExecutionFailed.
func IsUnsupportedTypeError ¶
IsUnsupportedTypeError checks if the error is a ConfigError with the code ErrUnsupportedType.
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 ¶
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 ¶
NewBuilder creates a new, empty configuration builder.
func (*Builder[C]) Add ¶
Add adds one or more options to the builder. It supports a fluent, chainable API.
func (*Builder[C]) AddWhen ¶
AddWhen conditionally adds an option to the builder if the condition is true. It supports a fluent, chainable API.
func (*Builder[C]) Apply ¶
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".
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 ¶
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.
type OptionE ¶
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 ¶
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 ¶
WithValidation creates an option that validates the target object. If the validator function returns an error, the configuration process will stop.