Documentation
¶
Overview ¶
Package interx provides lazy, context-aware sequence transformations for Go 1.23 iter.Seq values.
The interx package is useful when you want to build allocation-light data pipelines over slices, files, database rows, or generated streams without materializing every intermediate result. Each helper returns a new lazy sequence or consumes one directly, so work only happens when the caller ranges over the final sequence.
Example:
ctx := context.Background()
numbers := slices.Values([]int{1, 2, 3, 4, 5})
for v := range interx.Filter(ctx, numbers, func(n int) bool {
return n%2 == 0
}) {
fmt.Println(v)
}
Any important notes about behaviour such as laziness, context cancellation, memory usage. Most functions are lazy and stop as soon as the context is cancelled or the consumer breaks early. Reverse buffers the full sequence in memory before yielding results, while helpers like Filter, Map, and Take stream values one at a time.
Index ¶
- func Chunk[T any](ctx context.Context, seq iter.Seq[T], n int) iter.Seq[[]T]
- func Contains[T comparable](ctx context.Context, seq iter.Seq[T], target T) bool
- func Distinct[T comparable](ctx context.Context, seq iter.Seq[T]) iter.Seq[T]
- func Drain[T any](ctx context.Context, seq iter.Seq[T], fn func(T) error) error
- func Filter[T any](ctx context.Context, seq iter.Seq[T], fn func(T) bool) iter.Seq[T]
- func FlatMap[T, U any](ctx context.Context, seq iter.Seq[T], fn func(T) iter.Seq[U]) iter.Seq[U]
- func Flatten[T any](ctx context.Context, seq iter.Seq[[]T]) iter.Seq[T]
- func ForEach[T any](ctx context.Context, seq iter.Seq[T], fn func(T))
- func Map[T, U any](ctx context.Context, seq iter.Seq[T], fn func(T) U) iter.Seq[U]
- func Reverse[T any](ctx context.Context, seq iter.Seq[T]) iter.Seq[T]
- func Take[T any](ctx context.Context, seq iter.Seq[T], n int) iter.Seq[T]
- func TakeWhile[T any](ctx context.Context, seq iter.Seq[T], fn func(T) bool) iter.Seq[T]
- func Validate[T any](ctx context.Context, seq iter.Seq[T], fn func(T) (bool, string), ...) iter.Seq[T]
- func Zip[A, B any](ctx context.Context, a iter.Seq[A], b iter.Seq[B]) iter.Seq[[2]any]
- type ValidateConfig
- type ValidationError
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Chunk ¶
Chunk splits a sequence into slices of size n.
Example ¶
package main
import (
"context"
"fmt"
"slices"
vinterx "github.com/MostafaMagdSalama/vortex/interx"
)
func main() {
numbers := slices.Values([]int{1, 2, 3, 4, 5})
for batch := range vinterx.Chunk(context.Background(), numbers, 2) {
fmt.Println(batch)
}
}
Output: [1 2] [3 4] [5]
func Contains ¶
Contains returns true if the sequence contains the target value.
Example ¶
package main
import (
"context"
"fmt"
"slices"
vinterx "github.com/MostafaMagdSalama/vortex/interx"
)
func main() {
numbers := slices.Values([]int{1, 2, 3, 4, 5})
fmt.Println(vinterx.Contains(context.Background(), numbers, 3))
}
Output: true
func Distinct ¶
Distinct filters out duplicate values keeping only the first occurrence.
Example ¶
package main
import (
"context"
"fmt"
"slices"
vinterx "github.com/MostafaMagdSalama/vortex/interx"
)
func main() {
numbers := slices.Values([]int{1, 2, 1, 3, 2, 4})
for v := range vinterx.Distinct(context.Background(), numbers) {
fmt.Println(v)
}
}
Output: 1 2 3 4
func Drain ¶
Drain consumes a sequence and calls fn for each item. Stops immediately if ctx is cancelled or fn returns an error. Use Drain when your terminal operation can fail — writing to CSV, DB, files. Use ForEach when your terminal operation cannot fail — logging, printing.
example:
err := interx.Drain(ctx, users, func(u User) error {
return csvWriter.Write([]string{u.Name, u.Email})
})
Example ¶
package main
import (
"context"
"fmt"
"slices"
vinterx "github.com/MostafaMagdSalama/vortex/interx"
)
func main() {
numbers := slices.Values([]int{1, 2, 3})
_ = vinterx.Drain(context.Background(), numbers, func(n int) error {
fmt.Println(n)
return nil
})
}
Output: 1 2 3
func Filter ¶
Filter returns a new sequence containing only elements where fn returns true.
Example ¶
package main
import (
"context"
"fmt"
"slices"
vinterx "github.com/MostafaMagdSalama/vortex/interx"
)
func main() {
numbers := slices.Values([]int{1, 2, 3, 4, 5})
for v := range vinterx.Filter(context.Background(), numbers, func(n int) bool {
return n > 2
}) {
fmt.Println(v)
}
}
Output: 3 4 5
func FlatMap ¶
FlatMap transforms each element into a sequence, then flattens all sequences.
Example ¶
package main
import (
"context"
"fmt"
"iter"
"slices"
vinterx "github.com/MostafaMagdSalama/vortex/interx"
)
func main() {
numbers := slices.Values([]int{1, 2, 3})
for v := range vinterx.FlatMap(context.Background(), numbers, func(n int) iter.Seq[int] {
return slices.Values([]int{n, n * 10})
}) {
fmt.Println(v)
}
}
Output: 1 10 2 20 3 30
func Flatten ¶
Flatten converts a sequence of slices into a flat sequence of elements.
Example ¶
package main
import (
"context"
"fmt"
"slices"
vinterx "github.com/MostafaMagdSalama/vortex/interx"
)
func main() {
groups := slices.Values([][]int{{1, 2}, {3}, {4, 5}})
for v := range vinterx.Flatten(context.Background(), groups) {
fmt.Println(v)
}
}
Output: 1 2 3 4 5
func ForEach ¶
ForEach calls fn for every element in the sequence.
Example ¶
package main
import (
"context"
"fmt"
"slices"
vinterx "github.com/MostafaMagdSalama/vortex/interx"
)
func main() {
numbers := slices.Values([]int{1, 2, 3})
vinterx.ForEach(context.Background(), numbers, func(v int) {
fmt.Println(v * 2)
})
}
Output: 2 4 6
func Map ¶
Map transforms each element using fn.
Example ¶
package main
import (
"context"
"fmt"
"slices"
vinterx "github.com/MostafaMagdSalama/vortex/interx"
)
func main() {
numbers := slices.Values([]int{1, 2, 3})
for v := range vinterx.Map(context.Background(), numbers, func(n int) int {
return n * 10
}) {
fmt.Println(v)
}
}
Output: 10 20 30
func Reverse ¶
Reverse collects the sequence into memory and yields it in reverse order.
Example ¶
package main
import (
"context"
"fmt"
"slices"
vinterx "github.com/MostafaMagdSalama/vortex/interx"
)
func main() {
numbers := slices.Values([]int{1, 2, 3, 4, 5})
for v := range vinterx.Reverse(context.Background(), numbers) {
fmt.Println(v)
}
}
Output: 5 4 3 2 1
func Take ¶
Take returns the first n elements.
Example ¶
package main
import (
"context"
"fmt"
"slices"
vinterx "github.com/MostafaMagdSalama/vortex/interx"
)
func main() {
numbers := slices.Values([]int{1, 2, 3, 4, 5})
for v := range vinterx.Take(context.Background(), numbers, 3) {
fmt.Println(v)
}
}
Output: 1 2 3
func TakeWhile ¶
Example ¶
package main
import (
"context"
"fmt"
"slices"
vinterx "github.com/MostafaMagdSalama/vortex/interx"
)
func main() {
numbers := slices.Values([]int{1, 2, 3, 0, 4})
for v := range vinterx.TakeWhile(context.Background(), numbers, func(n int) bool {
return n > 0
}) {
fmt.Println(v)
}
}
Output: 1 2 3
func Validate ¶
func Validate[T any](ctx context.Context, seq iter.Seq[T], fn func(T) (bool, string), onError func(ValidationError[T])) iter.Seq[T]
Example ¶
package main
import (
"context"
"fmt"
"slices"
vinterx "github.com/MostafaMagdSalama/vortex/interx"
)
type User struct {
ID string
Name string
Email string
Status string
}
func validateUser(u User) (bool, string) {
if u.ID == "" {
return false, "missing ID"
}
if u.Name == "" {
return false, "missing name"
}
if u.Email == "" {
return false, "missing email"
}
if u.Status != "active" && u.Status != "inactive" {
return false, fmt.Sprintf("invalid status: %s", u.Status)
}
return true, ""
}
func main() {
users := slices.Values([]User{
{ID: "1", Name: "Alice", Email: "alice@example.com", Status: "active"},
{ID: "", Name: "Bob", Email: "bob@example.com", Status: "inactive"},
{ID: "3", Name: "Carol", Email: "carol@example.com", Status: "active"},
})
for user := range vinterx.Validate(context.Background(), users, validateUser, func(ve vinterx.ValidationError[User]) {
fmt.Println("invalid:", ve.Reason)
}) {
fmt.Println("valid:", user.Name)
}
}
Output: valid: Alice invalid: missing ID valid: Carol
func Zip ¶
Example ¶
package main
import (
"context"
"fmt"
"slices"
vinterx "github.com/MostafaMagdSalama/vortex/interx"
)
func main() {
left := slices.Values([]int{1, 2, 3})
right := slices.Values([]string{"a", "b", "c"})
for pair := range vinterx.Zip(context.Background(), left, right) {
fmt.Println(pair[0], pair[1])
}
}
Output: 1 a 2 b 3 c
Types ¶
type ValidateConfig ¶
type ValidateConfig[T any] struct { OnError func(ValidationError[T]) }
ValidateConfig controls what happens with invalid items.