Documentation ¶
Overview ¶
Package iterators provide iterator implementations.
Summary ¶
An iterator goal is to decouple the facts about the origin of the data, to the consumer who use the data. Most common scenario is to hide the fact if data is from a Certain DB, STDIN or from somewhere else. This helps to design data consumers that doesn't rely on the data source concrete implementation, while still able to do composition and different kind of actions on the received data stream. An Interface represent multiple data that can be 0 and infinite. As a general rule of thumb, if the consumer is not the final destination of the data stream, the consumer should use the pipeline pattern, in order to avoid bottleneck with local resources.
frameless.Iterator define a separate object that encapsulates accessing and traversing an aggregate object. Clients use an iterator to access and traverse an aggregate without knowing its representation (data structures). frameless.Iterator design inspirited by https://golang.org/pkg/encoding/json/#Decoder
Why an Object with empty interface instead of type safe channels to represent streams ¶
There are multiple approach to the same problem, and I only prefer this approach, because the error handling is easier trough this. In channel based pipeline pattern, you have to make sure that the information about the error is passed trough either trough some kind of separate error channel, or trough the message object it self that being passed around. If the pipeline can be composited during a certain use case, you can pass around a context.Context object to represent this. In the case of Interface pattern, this failure communicated during the individual iteration, which leaves it up to you to propagate the error forward, or handle at the place.
Resources ¶
https://en.wikipedia.org/wiki/Iterator_pattern https://en.wikipedia.org/wiki/Pipeline_(software)
Index ¶
- Constants
- func Collect[T any](i frameless.Iterator[T]) (vs []T, err error)
- func Count[T any](i frameless.Iterator[T]) (total int, err error)
- func Errorf[T any](format string, a ...interface{}) frameless.Iterator[T]
- func First[T any](i frameless.Iterator[T]) (value T, found bool, err error)
- func ForEach[T any](i frameless.Iterator[T], fn func(T) error) (rErr error)
- func Last[T any](i frameless.Iterator[T]) (value T, found bool, err error)
- func Map[T any, V any](iter frameless.Iterator[T], transform MapTransformFunc[T, V]) frameless.Iterator[V]
- func Pipe[T any]() (*PipeIn[T], *PipeOut[T])
- func WithCallback[T any](i frameless.Iterator[T], c Callback) frameless.Iterator[T]
- type Callback
- type CallbackIterator
- type ConcurrentAccessIterator
- type EmptyIter
- type Encoder
- type EncoderFunc
- type Error
- type FilterIter
- type MapIter
- type MapTransformFunc
- type Mock
- type PipeIn
- type PipeOut
- type SQLRowMapper
- type SQLRowMapperFunc
- type SQLRowScanner
- type SQLRows
- type SQLRowsIterator
- type Scanner
- type SingleValue
- type Slice
Examples ¶
Constants ¶
const Break frameless.Error = `iterators:break`
const ( // ErrClosed is the value that will be returned if a iterator has been closed but next decode is called ErrClosed frameless.Error = "Closed" )
Variables ¶
This section is empty.
Functions ¶
func Count ¶
Count will iterate over and count the total iterations number
Good when all you want is count all the elements in an iterator but don't want to do anything else.
func Map ¶
func Map[T any, V any](iter frameless.Iterator[T], transform MapTransformFunc[T, V]) frameless.Iterator[V]
Map allows you to do additional transformation on the values. This is useful in cases, where you have to alter the input value, or change the type all together. Like when you read lines from an input stream, and then you map the line content to a certain data structure, in order to not expose what steps needed in order to deserialize the input stream, thus protect the business rules from this information.
func Pipe ¶ added in v0.63.0
Pipe return a receiver and a sender. This can be used with resources that
Example ¶
package main import ( "github.com/adamluzsi/frameless/iterators" ) func main() { var ( i *iterators.PipeIn[int] o *iterators.PipeOut[int] ) i, o = iterators.Pipe[int]() _ = i // use it to send values _ = o // use it to consume values on each iteration (iter.Next()) }
Output:
Types ¶
type CallbackIterator ¶
func (*CallbackIterator[T]) Close ¶
func (i *CallbackIterator[T]) Close() error
type ConcurrentAccessIterator ¶
type ConcurrentAccessIterator[T any] struct { frameless.Iterator[T] // contains filtered or unexported fields }
func WithConcurrentAccess ¶
func WithConcurrentAccess[T any](i frameless.Iterator[T]) *ConcurrentAccessIterator[T]
WithConcurrentAccess allows you to convert any iterator into one that is safe to use from concurrent access. The caveat with this, that this protection only allows 1 Decode call for each Next call.
func (*ConcurrentAccessIterator[T]) Next ¶
func (i *ConcurrentAccessIterator[T]) Next() bool
func (*ConcurrentAccessIterator[T]) Value ¶ added in v0.63.0
func (i *ConcurrentAccessIterator[T]) Value() T
type EmptyIter ¶ added in v0.63.0
type EmptyIter[T any] struct{}
EmptyIter iterator can help achieve Null Object Pattern when no value is logically expected and iterator should be returned
type Encoder ¶
type Encoder interface { // // Encode encode a simple message back to the wrapped communication channel // message is an interface type because the channel communication layer and content and the serialization is up to the Encoder to implement // // If the message is a complex type that has multiple fields, // an exported struct that represent the content must be declared at the controller level // and all the presenters must based on that input for they test Encode(interface{}) error }
Encoder is a scope isolation boundary. One use-case for this is for example the Presenter object that encapsulate the external resource presentation mechanism from it's user.
Scope:
receive Entities, that will be used by the creator of the Encoder
type EncoderFunc ¶
type EncoderFunc func(interface{}) error
EncoderFunc is a wrapper to convert standalone functions into a presenter
func (EncoderFunc) Encode ¶
func (lambda EncoderFunc) Encode(i interface{}) error
Encode implements the Encoder Interface
type Error ¶
type Error[T any] struct { // contains filtered or unexported fields }
Error iterator can be used for returning an error wrapped with iterator interface. This can be used when external resource encounter unexpected non recoverable error during query execution.
type FilterIter ¶ added in v0.63.0
type FilterIter[T any] struct { Iterator frameless.Iterator[T] Filter func(T) bool // contains filtered or unexported fields }
func Filter ¶
func Filter[T any](i frameless.Iterator[T], filter func(T) bool) *FilterIter[T]
Example ¶
package main import ( "log" "github.com/adamluzsi/frameless" "github.com/adamluzsi/frameless/iterators" ) func main() { var iter frameless.Iterator[int] iter = iterators.NewSlice([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) iter = iterators.Filter[int](iter, func(n int) bool { return n > 2 }) defer iter.Close() for iter.Next() { n := iter.Value() _ = n } if err := iter.Err(); err != nil { log.Fatal(err) } }
Output:
func (*FilterIter[T]) Close ¶ added in v0.63.0
func (i *FilterIter[T]) Close() error
func (*FilterIter[T]) Err ¶ added in v0.63.0
func (i *FilterIter[T]) Err() error
func (*FilterIter[T]) Next ¶ added in v0.63.0
func (i *FilterIter[T]) Next() bool
func (*FilterIter[T]) Value ¶ added in v0.63.0
func (i *FilterIter[T]) Value() T
type MapIter ¶
type MapIter[T any, V any] struct { Iterator frameless.Iterator[T] Transform MapTransformFunc[T, V] // contains filtered or unexported fields }
type MapTransformFunc ¶
type Mock ¶
type Mock[T any] struct { Iterator frameless.Iterator[T] StubValue func() T StubClose func() error StubNext func() bool StubErr func() error }
func (*Mock[T]) ResetClose ¶
func (m *Mock[T]) ResetClose()
func (*Mock[T]) ResetValue ¶ added in v0.63.0
func (m *Mock[T]) ResetValue()
type PipeIn ¶ added in v0.41.0
PipeIn provides access to feed a pipe receiver with entities
func (*PipeIn[T]) Close ¶ added in v0.41.0
Close close the feed and err channel, which eventually notify the receiver that no more value expected
type PipeOut ¶ added in v0.41.0
type PipeOut[T any] struct { ValueChan <-chan T DoneChan chan<- struct{} ErrChan <-chan error // contains filtered or unexported fields }
PipeOut implements iterator interface while it's still being able to receive values, used for streaming
func (*PipeOut[T]) Close ¶ added in v0.41.0
Close sends a signal back that no more value should be sent because receiver stop listening
func (*PipeOut[T]) Err ¶ added in v0.41.0
Err returns an error object that the pipe sender want to present for the pipe receiver
type SQLRowMapper ¶
type SQLRowMapper[T any] interface { Map(s SQLRowScanner) (T, error) }
type SQLRowMapperFunc ¶
type SQLRowMapperFunc[T any] func(SQLRowScanner) (T, error)
func (SQLRowMapperFunc[T]) Map ¶
func (fn SQLRowMapperFunc[T]) Map(s SQLRowScanner) (T, error)
type SQLRowScanner ¶
type SQLRowScanner interface {
Scan(...interface{}) error
}
type SQLRowsIterator ¶
type SQLRowsIterator[T any] struct { Rows SQLRows Mapper SQLRowMapper[T] // contains filtered or unexported fields }
SQLRowsIterator allow you to use the same iterator pattern with sql.Rows structure. it allows you to do dynamic filtering, pipeline/middleware pattern on your sql results by using this wrapping around it. it also makes testing easier with the same Interface interface.
func NewSQLRows ¶
func NewSQLRows[T any](rows SQLRows, mapper SQLRowMapper[T]) *SQLRowsIterator[T]
func (*SQLRowsIterator[T]) Close ¶
func (i *SQLRowsIterator[T]) Close() error
func (*SQLRowsIterator[T]) Err ¶
func (i *SQLRowsIterator[T]) Err() error
func (*SQLRowsIterator[T]) Next ¶
func (i *SQLRowsIterator[T]) Next() bool
func (*SQLRowsIterator[T]) Value ¶ added in v0.63.0
func (i *SQLRowsIterator[T]) Value() T
type Scanner ¶
type SingleValue ¶ added in v0.63.0
type SingleValue[T any] struct { V T // contains filtered or unexported fields }
func NewSingleValue ¶ added in v0.63.0
func NewSingleValue[T any](v T) *SingleValue[T]
NewSingleValue creates an iterator that can return one single element and will ensure that Next can only be called once.
func (*SingleValue[T]) Close ¶ added in v0.63.0
func (i *SingleValue[T]) Close() error
func (*SingleValue[T]) Err ¶ added in v0.63.0
func (i *SingleValue[T]) Err() error
func (*SingleValue[T]) Next ¶ added in v0.63.0
func (i *SingleValue[T]) Next() bool
func (*SingleValue[T]) Value ¶ added in v0.63.0
func (i *SingleValue[T]) Value() T