package pipeline type Next[T any] func(T) error type Pipe[T any] func(T, Next[T]) error type Pipeline[T any] struct { passable T pipes []Pipe[T] } func Send[T any](passable T) *Pipeline[T] { return (&Pipeline[T]{}).Send(passable) } func (p *Pipeline[T]) Send(passable T) *Pipeline[T] { p.passable = passable return p } func (p *Pipeline[T]) Through(pipes ...Pipe[T]) *Pipeline[T] { p.pipes = pipes return p } func (p *Pipeline[T]) Then(destination Next[T]) error { next := destination for i := len(p.pipes) - 1; i >= 0; i-- { pipe := p.pipes[i] currentNext := next next = func(passable T) error { return pipe(passable, currentNext) } } return next(p.passable) }