Documentation
¶
Overview ¶
This package only contains some example which did not fit to other packages. See other packages' godoc for usage.
Example (Async_chunk) ¶
package main
import (
"context"
"fmt"
"sync"
"time"
"github.com/ngicks/go-iterator-helper/hiter"
"github.com/ngicks/go-iterator-helper/hiter/async"
)
func main() {
var (
wg sync.WaitGroup
in = make(chan int)
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
wg.Add(1)
go func() {
defer wg.Done()
ticker := time.NewTicker(500 * time.Nanosecond)
defer ticker.Stop()
_, _ = hiter.ChanSend(ctx, in, hiter.Tap(func(int) { <-ticker.C }, hiter.Range(0, 20)))
close(in)
}()
first := true
var count int
for c := range async.Chunk(time.Microsecond, 5, hiter.Chan(ctx, in)) {
count++
for _, i := range c {
if !first {
fmt.Print(", ")
}
first = false
fmt.Printf("%d", i)
}
}
fmt.Println()
wg.Wait()
fmt.Printf("count > 0 = %t\n", count > 0)
}
Output: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 count > 0 = true
Example (Async_worker_channel) ¶
Example async worker channel demonstrates usage of [hiter.Chan], [hiter.ChanSend]. It sends values from seq to worker running on separates goroutines. Workers work on values and then send results back to the main goroutine.
package main
import (
"context"
"fmt"
"maps"
"slices"
"sync"
"github.com/ngicks/go-iterator-helper/hiter"
"github.com/ngicks/go-iterator-helper/hiter/iterable"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
works := []string{"foo", "bar", "baz"}
in := make(chan string, 5)
out := make(chan hiter.KeyValue[string, error])
var wg sync.WaitGroup
wg.Add(3)
for range 3 {
go func() {
defer wg.Done()
_, _ = hiter.ChanSend(
ctx,
out,
hiter.Map(
func(s string) hiter.KeyValue[string, error] {
return hiter.KeyValue[string, error]{
K: "✨" + s + "✨" + s + "✨",
V: nil,
}
},
hiter.Chan(ctx, in),
),
)
}()
}
var wg2 sync.WaitGroup
wg2.Add(1)
go func() {
defer wg2.Done()
wg.Wait()
close(out)
}()
_, _ = hiter.ChanSend(ctx, in, slices.Values(works))
close(in)
results := maps.Collect(hiter.FromKeyValue(hiter.Chan(ctx, out)))
for result, err := range iterable.MapSorted[string, error](results).Iter2() {
fmt.Printf("result = %s, err = %v\n", result, err)
}
wg2.Wait()
}
Output: result = ✨bar✨bar✨, err = <nil> result = ✨baz✨baz✨, err = <nil> result = ✨foo✨foo✨, err = <nil>
Example (Async_worker_map) ¶
Example async worker map demonstrates usage of async.Map. At the surface it is similar to [hiter.Map2]. Actually it calls mapper in separate goroutine. If you don't care about order of element, just send values to workers through a channel and send back through another channel.
package main
import (
"context"
"fmt"
"slices"
"github.com/ngicks/go-iterator-helper/hiter/async"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
works := []string{"foo", "bar", "baz"}
// The order is kept.
for result, err := range async.Map(
ctx,
/*queueLimit*/ 10,
/*workerLimit*/ 5,
/*mapper*/ func(ctx context.Context, s string) (string, error) {
return "✨" + s + "✨" + s + "✨", nil
},
slices.Values(works),
) {
fmt.Printf("result = %s, err = %v\n", result, err)
}
}
Output: result = ✨foo✨foo✨, err = <nil> result = ✨bar✨bar✨, err = <nil> result = ✨baz✨baz✨, err = <nil>
Example (Async_worker_map_graceful_cancellation) ¶
package main
import (
"context"
"fmt"
"slices"
"github.com/ngicks/go-iterator-helper/hiter/async"
"github.com/ngicks/go-iterator-helper/hiter/mapper"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
works := []string{"foo", "bar", "baz"}
workerCtx, cancelWorker := context.WithCancel(context.Background())
defer cancelWorker()
for result, err := range async.Map(
ctx,
/*queueLimit*/ 1,
/*workerLimit*/ 1,
/*mapper*/ func(ctx context.Context, s string) (string, error) {
combined, cancel := context.WithCancel(ctx)
defer cancel()
go func() {
select {
case <-ctx.Done():
case <-combined.Done():
case <-workerCtx.Done():
}
cancel()
}()
if combined.Err() != nil {
return "", combined.Err()
}
return "✨" + s + "✨" + s + "✨", nil
},
mapper.Cancellable(1, workerCtx, slices.Values(works)),
) {
fmt.Printf("result = %s, err = %v\n", result, err)
cancelWorker()
}
}
Output: result = ✨foo✨foo✨, err = <nil> result = ✨bar✨bar✨, err = <nil>
Example (Dec_enc_round_trip) ¶
package main
import (
"bytes"
"encoding/json"
"fmt"
"maps"
"os"
"github.com/ngicks/go-iterator-helper/hiter"
"github.com/ngicks/go-iterator-helper/hiter/encodingiter"
"github.com/ngicks/go-iterator-helper/hiter/errbox"
)
func main() {
src := []byte(`
{"foo":"foo"}
{"bar":"bar"}
{"baz":"baz"}
`)
rawDec := json.NewDecoder(bytes.NewReader(src))
dec := errbox.New(encodingiter.Decode[map[string]string](rawDec))
enc := json.NewEncoder(os.Stdout)
err := encodingiter.Encode(
enc,
hiter.Map(
func(m map[string]string) map[string]string {
return maps.Collect(
hiter.Map2(
func(k, v string) (string, string) { return k + k, v + v },
maps.All(m),
),
)
},
dec.IntoIter(),
),
)
fmt.Printf("dec error = %v\n", dec.Err())
fmt.Printf("enc error = %v\n", err)
}
Output: {"foofoo":"foofoo"} {"barbar":"barbar"} {"bazbaz":"bazbaz"} dec error = <nil> enc error = <nil>
Example (Error_handle) ¶
Example error handle demonstrates various way to handle error.
package main
import (
"errors"
"fmt"
"slices"
"github.com/ngicks/go-iterator-helper/hiter"
"github.com/ngicks/go-iterator-helper/hiter/errbox"
"github.com/ngicks/go-iterator-helper/hiter/mapper"
)
func main() {
var (
errSample = errors.New("sample")
errSample2 = errors.New("sample2")
)
erroneous := hiter.Pairs(
hiter.Range(0, 6),
hiter.Concat(
hiter.Repeat(error(nil), 2),
hiter.Repeat(errSample2, 2),
hiter.Once(errSample),
hiter.Once(error(nil)),
),
)
fmt.Println("TryFind:")
v, idx, err := hiter.TryFind(func(i int) bool { return i > 0 }, erroneous)
fmt.Printf("v = %d, idx = %d, err = %v\n", v, idx, err)
v, idx, err = hiter.TryFind(func(i int) bool { return i > 5 }, erroneous)
fmt.Printf("v = %d, idx = %d, err = %v\n", v, idx, err)
fmt.Println()
fmt.Println("TryForEach:")
err = hiter.TryForEach(func(i int) { fmt.Printf("i = %d\n", i) }, erroneous)
fmt.Printf("err = %v\n", err)
fmt.Println()
fmt.Println("TryReduce:")
collected, err := hiter.TryReduce(func(c []int, i int) []int { return append(c, i) }, nil, erroneous)
fmt.Printf("collected = %#v, err = %v\n", collected, err)
fmt.Println()
fmt.Println("HandleErr:")
var handled error
collected = slices.Collect(
mapper.HandleErr(
func(i int, err error) bool {
handled = err
return errors.Is(err, errSample2)
},
erroneous,
),
)
fmt.Printf("collected = %#v, err = %v\n", collected, handled)
fmt.Println()
fmt.Println("*errbox.Box:")
box := errbox.New(erroneous)
collected = slices.Collect(box.IntoIter())
fmt.Printf("collected = %#v, err = %v\n", collected, box.Err())
fmt.Println()
}
Output: TryFind: v = 1, idx = 1, err = <nil> v = 0, idx = -1, err = sample2 TryForEach: i = 0 i = 1 err = sample2 TryReduce: collected = []int{0, 1}, err = sample2 HandleErr: collected = []int{0, 1}, err = sample *errbox.Box: collected = []int{0, 1}, err = sample2
Example (Peek_and_continue) ¶
package main
import (
"fmt"
"github.com/ngicks/go-iterator-helper/hiter"
"github.com/ngicks/go-iterator-helper/hiter/iterable"
)
func main() {
// iterator that yields 0 to 9 sequentially.
src := hiter.Range(0, 10)
fmt.Println("It replays data if break-ed and resumed.")
count := 3
first := true
for v := range src {
count--
if count < 0 {
break
}
if !first {
fmt.Print(", ")
}
first = false
fmt.Printf("%d", v)
}
fmt.Println()
fmt.Println("break and resume")
first = true
for v := range hiter.Limit(3, src) {
if !first {
fmt.Print(", ")
}
first = false
fmt.Printf("%d", v)
}
fmt.Print("\n\n")
fmt.Println("converting it to be resumable.")
resumable := iterable.NewResumable(src)
v0, _ := hiter.First(resumable.IntoIter())
fmt.Printf("first: %d\n", v0)
v1, _ := hiter.First(resumable.IntoIter())
fmt.Printf("second: %d\n", v1)
fmt.Println()
fmt.Println("reconnect them to whole iterator.")
first = true
for v := range hiter.Concat(hiter.Once(v0), hiter.Once(v1), resumable.IntoIter()) {
if !first {
fmt.Print(", ")
}
first = false
fmt.Printf("%d", v)
}
fmt.Println()
fmt.Println("\nYou can achieve above also with iterable.Peekable")
peekable := iterable.NewPeekable(src)
fmt.Printf("%#v\n", peekable.Peek(5))
first = true
for v := range peekable.IntoIter() {
if !first {
fmt.Print(", ")
}
first = false
fmt.Printf("%d", v)
}
fmt.Println()
}
Output: It replays data if break-ed and resumed. 0, 1, 2 break and resume 0, 1, 2 converting it to be resumable. first: 0 second: 1 reconnect them to whole iterator. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 You can achieve above also with iterable.Peekable []int{0, 1, 2, 3, 4} 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Example (Teeing) ¶
package main
import (
"fmt"
"sync"
"github.com/ngicks/go-iterator-helper/hiter"
"github.com/ngicks/go-iterator-helper/hiter/tee"
)
func main() {
src := hiter.Range(0, 5)
seqPiped, seq := tee.TeeSeqPipe(0, src)
var found bool
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
found = hiter.Contains(3, seqPiped.IntoIter())
// Don't forget to discard all elements from seq!
// Without this, tee could not proceed.
hiter.Discard(seqPiped.IntoIter())
}()
for i := range hiter.Map(func(i int) int { return i * i }, seq.IntoIter()) {
fmt.Printf("i = %02d\n", i)
}
wg.Wait()
fmt.Printf("\nfound=%t\n", found)
}
Output: i = 00 i = 01 i = 04 i = 09 i = 16 found=true
Directories
¶
| Path | Synopsis |
|---|---|
|
hiter defines iterator sources from various inputs, adapters, collectors.
|
hiter defines iterator sources from various inputs, adapters, collectors. |
|
async
The package async defines asynchronous adapters.
|
The package async defines asynchronous adapters. |
|
bufioiter
bufioiter defines iterator source/collector that corresponds to std library `bufio`.
|
bufioiter defines iterator source/collector that corresponds to std library `bufio`. |
|
containeriter
containeriter defines iterator source/collector that corresponds to std library `container/*`.
|
containeriter defines iterator source/collector that corresponds to std library `container/*`. |
|
cryptoiter
cryptoiter defines iterator source/collector that corresponds to std `crypto/*`.
|
cryptoiter defines iterator source/collector that corresponds to std `crypto/*`. |
|
databaseiter
databaseiter defines iterator source/collector that corresponds to std library `database/*`.
|
databaseiter defines iterator source/collector that corresponds to std library `database/*`. |
|
encodingiter
encodingiter defines iterator source/collector that corresponds to std library `encoding` and all its descendants (`encoding/*`)
|
encodingiter defines iterator source/collector that corresponds to std library `encoding` and all its descendants (`encoding/*`) |
|
errbox
errbox boxes iter.Seq[V, error] and converts to iter.Seq[V].
|
errbox boxes iter.Seq[V, error] and converts to iter.Seq[V]. |
|
ioiter
ioiter defines iterator source/collector that corresponds to std library `io/*`.
|
ioiter defines iterator source/collector that corresponds to std library `io/*`. |
|
iterable
Wrapper for iterable objects; heap, list, ring, slice, map, channel, etc.
|
Wrapper for iterable objects; heap, list, ring, slice, map, channel, etc. |
|
iterreader
iterreader defines functions that converts an iterator to io.Reader.
|
iterreader defines functions that converts an iterator to io.Reader. |
|
mapper
package mapper is collection of small mapping helpers.
|
package mapper is collection of small mapping helpers. |
|
mathiter
mathiter defines iterator source/collector that corresponds to std `math/*`.
|
mathiter defines iterator source/collector that corresponds to std `math/*`. |
|
reflectiter
reflectiter defines iterator source/collector that corresponds to std library `reflect`.
|
reflectiter defines iterator source/collector that corresponds to std library `reflect`. |
|
stringsiter
stringsiter defines iterator source/collector that corresponds to std library `strings`.
|
stringsiter defines iterator source/collector that corresponds to std library `strings`. |
|
internal
|
|
|
x
|
|
|
exp/xiter
Code copied from
|
Code copied from |
Click to show internal directories.
Click to hide internal directories.