option
Functional options pattern support with generics.
Import
go
import "github.com/foomo/go/option"Types
go
type Option[T any] func(T)
type OptionE[T any] func(T) errorAPI
Apply
go
func Apply[T any](v T, opts ...Option[T])Applies each option function to the value.
ApplyE
go
func ApplyE[T any](v T, opts ...OptionE[T]) errorApplies each option function to the value, stopping and returning on the first error.
Build
go
func Build[T any](v T, builders ...interface{ List() []Option[T] })Applies options from one or more builders to the value. Nil builders are safely skipped.
BuildE
go
func BuildE[T any](v T, builders ...interface{ List() []OptionE[T] }) errorApplies options from one or more error-returning builders to the value, stopping and returning on the first error.
Types
Builder
go
type Builder[T any] struct {
Opts []Option[T]
}
func (b *Builder[T]) List() []Option[T]A generic option builder that collects functional options. Embed it in domain-specific builders to group related options.
BuilderE
go
type BuilderE[T any] struct {
Opts []OptionE[T]
}
func (b *BuilderE[T]) List() []OptionE[T]A generic option builder that collects error-returning functional options.
Example
go
package main
import (
"fmt"
"github.com/foomo/go/option"
)
type Server struct {
Name string
Port int
}
func WithName(name string) option.Option[*Server] {
return func(s *Server) {
s.Name = name
}
}
func WithPort(port int) option.Option[*Server] {
return func(s *Server) {
s.Port = port
}
}
func main() {
s := &Server{}
option.Apply(s, WithName("localhost"), WithPort(8080))
fmt.Println(s.Name) // localhost
fmt.Println(s.Port) // 8080
}Using Builders
go
type ServerBuilder struct {
option.Builder[*Server]
}
func (b *ServerBuilder) Name(name string) *ServerBuilder {
b.Opts = append(b.Opts, WithName(name))
return b
}
func (b *ServerBuilder) Port(port int) *ServerBuilder {
b.Opts = append(b.Opts, WithPort(port))
return b
}
func main() {
s := &Server{}
b := &ServerBuilder{}
option.Build(s, b.Name("localhost").Port(8080))
fmt.Println(s.Name) // localhost
fmt.Println(s.Port) // 8080
}Error handling with ApplyE
go
func WithValidatedPort(port int) option.OptionE[*Server] {
return func(s *Server) error {
if port < 1 || port > 65535 {
return fmt.Errorf("invalid port: %d", port)
}
s.Port = port
return nil
}
}
err := option.ApplyE(s, WithValidatedPort(99999))
// err: invalid port: 99999