goter

package module
v0.0.0-...-75bb475 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 25, 2025 License: MIT Imports: 4 Imported by: 0

README

Goter - Go Iterator Library

Go Version

Goter is a Go iterator library that provides convenient tools for creating iterators with context support and various types of sequences. Built for Go 1.23+ with native iterator support.

Features

  • ✅ Context support for operation cancellation
  • ✅ Generic types for type safety
  • ✅ Number iterators with various types
  • ✅ Time-delayed iterators
  • ✅ Step and range iterators
  • ✅ Overflow protection
  • ✅ Zero external dependencies

Package Organization

The library is organized into logical modules:

  • core.go - Core wrapper functions (Wrap, Wrap2) and type constraints
  • ranges.go - Range-based iterators (Range, Count, Step, Numbers, NumberRange)
  • generators.go - Sequence generators (Repeat, Cycle, Generate, Fibonacci, Ticker)
  • utils.go - Utility iterators (Enumerate, Chunk, Window, Slice, Take, Skip)
  • strings.go - String-specific iterators (Lines, Words, Runes, Bytes, Split, FilterRunes, etc.)

Installation

go get github.com/goregion/goter

Quick Start

package main

import (
    "context"
    "fmt"
    "github.com/goregion/goter"
)

func main() {
    ctx := context.Background()
    
    // Range iterator [0, 10)
    for i := range goter.Range(ctx, 0, 10) {
        fmt.Println(i) // 0, 1, 2, ..., 9
    }
    
    // String processing
    text := "Hello\nWorld\nFrom Go!"
    for line := range goter.Lines(ctx, text) {
        fmt.Printf("Line: %s\n", line)
    }
    
    // Unicode-aware string iteration
    emoji := "Hello 🌍!"
    for r := range goter.Runes(ctx, emoji) {
        fmt.Printf("Rune: %c\n", r)
    }
}

Usage Examples

Basic Context-Aware Iterators
ctx := context.Background()

// Simple iterator with context support
data := []int{1, 2, 3, 4, 5}
simpleIter := func(yield func(int) bool) {
    for _, v := range data {
        if !yield(v) {
            return
        }
    }
}

for v := range goter.Wrap(ctx, simpleIter) {
    fmt.Println(v) // 1, 2, 3, 4, 5
}
Range Iterators
ctx := context.Background()

// Range [0, 10)
for i := range goter.Range(ctx, 0, 10) {
    fmt.Println(i) // 0, 1, 2, ..., 9
}

// Counter [0, n)
for i := range goter.Count(ctx, 5) {
    fmt.Println(i) // 0, 1, 2, 3, 4
}

// Range with step
for i := range goter.Step(ctx, 0, 10, 2) {
    fmt.Println(i) // 0, 2, 4, 6, 8
}

// Reverse range with negative step
for i := range goter.Step(ctx, 10, 0, -2) {
    fmt.Println(i) // 10, 8, 6, 4, 2
}
Number Iterators with Type Safety
ctx := context.Background()

// Iterator for specific range with type safety
for i := range goter.NumberRange(ctx, int8(120), int8(127)) {
    fmt.Println(i) // 120, 121, 122, 123, 124, 125, 126, 127
}

// Iterator for all values of type (use with caution)
for i := range goter.Numbers[uint8](ctx) {
    if i > 10 {
        break // Stop after first 11 values (0-10)
    }
    fmt.Println(i)
}
Time-Based Iterators
import "time"

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

startTime := time.Now()
interval := 1 * time.Second

for timestamp := range goter.Ticker(ctx, startTime, interval) {
    fmt.Printf("Tick at: %v\n", timestamp)
    // Executes every second until context is cancelled
}
Key-Value Pair Iterators
ctx := context.Background()

data := map[string]int{"a": 1, "b": 2, "c": 3}
mapIter := func(yield func(string, int) bool) {
    for k, v := range data {
        if !yield(k, v) {
            return
        }
    }
}

for k, v := range goter.Wrap2(ctx, mapIter) {
    fmt.Printf("%s: %d\n", k, v)
}
Utility Functions
ctx := context.Background()

// Enumerate with index
data := []string{"apple", "banana", "cherry"}
sliceIter := goter.Slice(ctx, data)

for i, fruit := range goter.Enumerate(ctx, sliceIter) {
    fmt.Printf("%d: %s\n", i, fruit) // 0: apple, 1: banana, 2: cherry
}

// Chunk data into groups
numbers := goter.Range(ctx, 0, 10) // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

for chunk := range goter.Chunk(ctx, numbers, 3) {
    fmt.Println(chunk) // [0 1 2], [3 4 5], [6 7 8], [9]
}

String Processing Examples

The library includes powerful string processing iterators that handle Unicode correctly:

package main

import (
    "context"
    "fmt"
    "github.com/goregion/goter"
)

func main() {
    ctx := context.Background()

    // Processing lines
    document := "Line 1\nLine 2\n\nLine 4"
    for line := range goter.Lines(ctx, document) {
        fmt.Printf("Processing: '%s'\n", line)
    }

    // Word extraction
    sentence := "Hello   world\tfrom\nGo!"
    words := make([]string, 0)
    for word := range goter.Words(ctx, sentence) {
        words = append(words, word)
    }
    fmt.Printf("Words: %v\n", words) // [Hello world from Go!]

    // Unicode-safe character processing
    text := "Hello 🌍!"
    for r := range goter.Runes(ctx, text) {
        fmt.Printf("Rune: %c (U+%04X)\n", r, r)
    }

    // Character filtering
    mixed := "abc123XYZ456"
    isDigit := func(r rune) bool { return r >= '0' && r <= '9' }
    fmt.Print("Digits: ")
    for r := range goter.FilterRunes(ctx, mixed, isDigit) {
        fmt.Printf("%c", r) // 123456
    }
    fmt.Println()

    // CSV processing
    csvLine := "John,25,Engineer,New York"
    for value := range goter.Split(ctx, csvLine, ",") {
        fmt.Printf("Field: %s\n", value)
    }

    // Generate all 3-character substrings
    word := "programming"
    for substr := range goter.Substrings(ctx, word, 3) {
        fmt.Printf("Substring: %s\n", substr)
    }
}
Cancellation Support
ctx, cancel := context.WithCancel(context.Background())

go func() {
    time.Sleep(2 * time.Second)
    cancel() // Cancel operation after 2 seconds
}()

for i := range goter.Count(ctx, 1000000) {
    fmt.Println(i)
    time.Sleep(500 * time.Millisecond)
    // Iteration will stop after ~2 seconds due to context cancellation
}

API Reference

Core Functions
  • Wrap[T](ctx, iter.Seq[T]) iter.Seq[T] - Adds context support to existing iterator
  • Wrap2[K, V](ctx, iter.Seq2[K, V]) iter.Seq2[K, V] - Adds context support to key-value iterator
Range Functions
  • Range[T](ctx, start, end T) iter.Seq[T] - Creates range iterator [start, end)
  • Count[T](ctx, n T) iter.Seq[T] - Creates counter iterator [0, n)
  • Step[T](ctx, start, end, step T) iter.Seq[T] - Creates range iterator with step
  • NumberRange[T](ctx, start, end T) iter.Seq[T] - Creates inclusive range [start, end]
  • Numbers[T](ctx) iter.Seq[T] - Creates iterator for all values of integer type
Generator Functions
  • Ticker(ctx, startTime, duration) iter.Seq[time.Time] - Creates time-based iterator
  • Repeat[T](ctx, value T, count) iter.Seq[T] - Repeats value specified times
  • Cycle[T](ctx, slice) iter.Seq[T] - Cycles through slice elements infinitely
  • Generate[T](ctx, generator) iter.Seq[T] - Generates values using function
  • Fibonacci(ctx) iter.Seq[uint64] - Generates Fibonacci sequence
Utility Functions
  • Enumerate[T](ctx, iter.Seq[T]) iter.Seq2[int, T] - Pairs elements with indices
  • Chunk[T](ctx, iter.Seq[T], size) iter.Seq[[]T] - Groups elements into slices
  • Window[T](ctx, iter.Seq[T], size) iter.Seq[[]T] - Creates sliding window
  • Slice[T](ctx, []T) iter.Seq[T] - Converts slice to iterator
  • Take[T](ctx, iter.Seq[T], n) iter.Seq[T] - Takes first n elements
  • Skip[T](ctx, iter.Seq[T], n) iter.Seq[T] - Skips first n elements
String Functions
  • Lines(ctx, string) iter.Seq[string] - Splits string into lines
  • Words(ctx, string) iter.Seq[string] - Splits string into words
  • Runes(ctx, string) iter.Seq[rune] - Iterates over Unicode runes
  • Bytes(ctx, string) iter.Seq[byte] - Iterates over raw bytes
  • Split(ctx, string, sep) iter.Seq[string] - Splits string by separator
  • SplitN(ctx, string, sep, n) iter.Seq[string] - Splits string with limit
  • RuneIndexes(ctx, string) iter.Seq2[int, rune] - Pairs runes with byte indexes
  • FilterRunes(ctx, string, predicate) iter.Seq[rune] - Filters runes by predicate
  • Substrings(ctx, string, length) iter.Seq[string] - Generates all substrings of given length
  • Prefixes(ctx, string) iter.Seq[string] - Generates all prefixes
  • Suffixes(ctx, string) iter.Seq[string] - Generates all suffixes
  • Permutations(ctx, string) iter.Seq[string] - Generates all character permutations
Type Constraints
  • integer - Constraint for all Go integer types (int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr)

Testing

# Run all tests
go test ./...

# Run tests with verbose output
go test -v ./...

# Run benchmark tests
go test -bench=. -benchmem ./...

Safety Features

The library provides several safety guarantees:

  1. Overflow Protection - Number iterators prevent infinite loops on integer overflow
  2. Resource Management - Timers and resources are properly cleaned up on context cancellation
  3. Type Safety - Generic constraints ensure compile-time type safety
  4. Graceful Cancellation - All iterators respect context cancellation for cooperative termination

Requirements

  • Go 1.23 or later (for native iterator support)
  • No external dependencies

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Bytes

func Bytes(ctx context.Context, s string) iter.Seq[byte]

Bytes creates an iterator that yields bytes from a string. Note: This iterates over raw bytes, not Unicode code points.

Example:

ctx := context.Background()
text := "Hello"
for b := range goter.Bytes(ctx, text) {
	fmt.Printf("Byte: %c (0x%02X)\n", b, b)
	// Output:
	// Byte: H (0x48)
	// Byte: e (0x65)
	// ...
}

func Chunk

func Chunk[T any](ctx context.Context, iterator iter.Seq[T], size int) iter.Seq[[]T]

Chunk creates an iterator that groups elements from the source iterator into slices of specified size. The last chunk may contain fewer elements if the total number doesn't divide evenly.

Example:

ctx := context.Background()
numbers := goter.Range(ctx, 0, 10) // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

for chunk := range goter.Chunk(ctx, numbers, 3) {
	fmt.Println(chunk) // [0 1 2], [3 4 5], [6 7 8], [9]
}

func Count

func Count[Type integer](ctx context.Context, n Type) iter.Seq[Type]

Count creates an iterator that counts from 0 to n-1 (half-open range [0, n)). This is a convenience function equivalent to Range(ctx, 0, n). It's particularly useful for iterating a specific number of times.

Example:

ctx := context.Background()
for i := range goter.Count(ctx, 5) {
	fmt.Printf("Iteration %d\n", i) // Prints iterations 0, 1, 2, 3, 4
}

func Cycle

func Cycle[T any](ctx context.Context, values []T) iter.Seq[T]

Cycle creates an iterator that infinitely cycles through a slice of values. The iterator stops when the context is cancelled or when the consumer stops.

Example:

ctx := context.Background()
colors := []string{"red", "green", "blue"}
count := 0
for color := range goter.Cycle(ctx, colors) {
	fmt.Println(color) // red, green, blue, red, green, blue, ...
	count++
	if count >= 7 { break } // Stop after 7 elements
}

func Enumerate

func Enumerate[T any](ctx context.Context, iterator iter.Seq[T]) iter.Seq2[int, T]

Enumerate creates an iterator that pairs each element with its index. Returns iter.Seq2 where the first value is the index and the second is the element.

Example:

ctx := context.Background()
data := []string{"apple", "banana", "cherry"}
slice_iter := goter.Slice(ctx, data)

for i, fruit := range goter.Enumerate(ctx, slice_iter) {
	fmt.Printf("%d: %s\n", i, fruit) // 0: apple, 1: banana, 2: cherry
}

func Fibonacci

func Fibonacci(ctx context.Context) iter.Seq[uint64]

Fibonacci creates an iterator that generates Fibonacci numbers. The sequence starts with 0, 1 and continues indefinitely until context cancellation.

Example:

ctx := context.Background()
count := 0
for fib := range goter.Fibonacci(ctx) {
	fmt.Println(fib) // 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
	count++
	if count >= 10 { break }
}

func FilterRunes

func FilterRunes(ctx context.Context, s string, predicate func(rune) bool) iter.Seq[rune]

FilterRunes creates an iterator that yields runes from a string that satisfy a predicate. This is useful for filtering out unwanted characters or selecting specific ones.

Example:

ctx := context.Background()
text := "Hello123World456"

// Get only letters (using custom predicate)
isLetter := func(r rune) bool { return (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') }
for r := range goter.FilterRunes(ctx, text, isLetter) {
	fmt.Printf("%c", r) // HelloWorld
}

// Get only digits
isDigit := func(r rune) bool { return r >= '0' && r <= '9' }
for r := range goter.FilterRunes(ctx, text, isDigit) {
	fmt.Printf("%c", r) // 123456
}

func Generate

func Generate[T any](ctx context.Context, generator func() T) iter.Seq[T]

Generate creates an iterator that generates values using a generator function. The generator is called for each element until the context is cancelled.

Example:

ctx := context.Background()
counter := 0
generator := func() int {
	counter += 2
	return counter
}

count := 0
for val := range goter.Generate(ctx, generator) {
	fmt.Println(val) // 2, 4, 6, 8, 10, ...
	count++
	if count >= 5 { break }
}

func Lines

func Lines(ctx context.Context, s string) iter.Seq[string]

Lines creates an iterator that yields lines from a string. Lines are split by '\n', and empty lines are included.

Example:

ctx := context.Background()
text := "Hello\nWorld\n\nLast line"
for line := range goter.Lines(ctx, text) {
	fmt.Printf("Line: '%s'\n", line)
	// Output:
	// Line: 'Hello'
	// Line: 'World'
	// Line: ''
	// Line: 'Last line'
}

func NumberRange

func NumberRange[Type integer](ctx context.Context, start, end Type) iter.Seq[Type]

NumberRange creates an iterator that generates values in the inclusive range [start, end]. This function includes overflow protection to prevent infinite loops when the end value equals the maximum value of the integer type.

The iterator respects context cancellation and will stop immediately when the context is done.

Example:

ctx := context.Background()
for i := range goter.NumberRange(ctx, 5, 10) {
	fmt.Println(i) // Prints: 5, 6, 7, 8, 9, 10
}

func Numbers

func Numbers[Type integer](ctx context.Context) iter.Seq[Type]

Numbers creates an iterator that generates all values from 0 to the maximum value of the specified integer type. This is useful for exhaustive iterations over a type's range.

WARNING: This iterator can run for a very long time for larger integer types. Consider using NumberRange for bounded ranges.

Example:

ctx := context.Background()
for i := range goter.Numbers[uint8](ctx) {
	if i > 10 {
		break // Stop after first 11 values (0-10)
	}
	fmt.Println(i)
}

func Permutations

func Permutations(ctx context.Context, s string) iter.Seq[string]

Permutations creates an iterator that yields all permutations of the characters in a string. Warning: The number of permutations grows factorially with string length!

Example:

ctx := context.Background()
text := "abc"
for perm := range goter.Permutations(ctx, text) {
	fmt.Printf("Permutation: '%s'\n", perm)
	// Output:
	// Permutation: 'abc'
	// Permutation: 'acb'
	// Permutation: 'bac'
	// Permutation: 'bca'
	// Permutation: 'cab'
	// Permutation: 'cba'
}

func Prefixes

func Prefixes(ctx context.Context, s string) iter.Seq[string]

Prefixes creates an iterator that yields all non-empty prefixes of a string. Prefixes are yielded in order of increasing length.

Example:

ctx := context.Background()
text := "Hello"
for prefix := range goter.Prefixes(ctx, text) {
	fmt.Printf("Prefix: '%s'\n", prefix)
	// Output:
	// Prefix: 'H'
	// Prefix: 'He'
	// Prefix: 'Hel'
	// Prefix: 'Hell'
	// Prefix: 'Hello'
}

func Range

func Range[Type integer](ctx context.Context, start, end Type) iter.Seq[Type]

Range creates an iterator for the half-open range [start, end). This is similar to Python's range() function or Go's traditional for loop. The iterator stops before reaching the end value, making it useful for array indexing and other common iteration patterns.

Example:

ctx := context.Background()
for i := range goter.Range(ctx, 2, 8) {
	fmt.Println(i) // Prints: 2, 3, 4, 5, 6, 7 (end=8 is excluded)
}

func Repeat

func Repeat[T any](ctx context.Context, value T, n int) iter.Seq[T]

Repeat creates an iterator that repeats a value n times. If n is negative, the value is repeated infinitely until context is cancelled.

Example:

ctx := context.Background()
for msg := range goter.Repeat(ctx, "hello", 3) {
	fmt.Println(msg) // Prints: hello, hello, hello
}

// Infinite repeat (until context cancellation)
for val := range goter.Repeat(ctx, 42, -1) {
	fmt.Println(val) // Prints 42 forever until cancelled
	if someCondition { break }
}

func RuneIndexes

func RuneIndexes(ctx context.Context, s string) iter.Seq2[int, rune]

RuneIndexes creates an iterator that yields pairs of rune and its byte index in the string. This is useful when you need to know the position of each rune for substring operations.

Example:

ctx := context.Background()
text := "Hello 🌍!"
for index, r := range goter.RuneIndexes(ctx, text) {
	fmt.Printf("Rune: %c at byte index %d\n", r, index)
	// Output:
	// Rune: H at byte index 0
	// Rune: e at byte index 1
	// ...
	// Rune: 🌍 at byte index 6
	// Rune: ! at byte index 10
}

func Runes

func Runes(ctx context.Context, s string) iter.Seq[rune]

Runes creates an iterator that yields runes (Unicode code points) from a string. This correctly handles multi-byte UTF-8 characters.

Example:

ctx := context.Background()
text := "Hello 🌍"
for r := range goter.Runes(ctx, text) {
	fmt.Printf("Rune: %c (U+%04X)\n", r, r)
	// Output:
	// Rune: H (U+0048)
	// Rune: e (U+0065)
	// ...
	// Rune: 🌍 (U+1F30D)
}

func Skip

func Skip[T any](ctx context.Context, iterator iter.Seq[T], n int) iter.Seq[T]

Skip creates an iterator that skips the first n elements and yields the rest.

Example:

ctx := context.Background()
numbers := goter.Range(ctx, 0, 10) // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

for num := range goter.Skip(ctx, numbers, 3) {
	fmt.Println(num) // 3, 4, 5, 6, 7, 8, 9 (skipped first 3)
}

func Slice

func Slice[T any](ctx context.Context, slice []T) iter.Seq[T]

Slice creates an iterator that yields elements from a slice. This is a convenience function for iterating over slices with context support.

Example:

ctx := context.Background()
data := []int{10, 20, 30, 40, 50}

for value := range goter.Slice(ctx, data) {
	fmt.Println(value) // 10, 20, 30, 40, 50
}

func Split

func Split(ctx context.Context, s, sep string) iter.Seq[string]

Split creates an iterator that yields substrings split by a separator. Empty strings are included if they occur between separators.

Example:

ctx := context.Background()
text := "apple,banana,,cherry"
for part := range goter.Split(ctx, text, ",") {
	fmt.Printf("Part: '%s'\n", part)
	// Output:
	// Part: 'apple'
	// Part: 'banana'
	// Part: ''
	// Part: 'cherry'
}

func SplitN

func SplitN(ctx context.Context, s, sep string, n int) iter.Seq[string]

SplitN creates an iterator that yields at most n substrings split by a separator. If n < 0, there is no limit on the number of substrings.

Example:

ctx := context.Background()
text := "a,b,c,d,e"
for part := range goter.SplitN(ctx, text, ",", 3) {
	fmt.Printf("Part: '%s'\n", part)
	// Output:
	// Part: 'a'
	// Part: 'b'
	// Part: 'c,d,e'
}

func Step

func Step[Type integer](ctx context.Context, start, end, step Type) iter.Seq[Type]

Step creates an iterator with a custom step size between start and end. The step can be positive (ascending) or negative (descending). A zero step is safe and will produce no values to prevent infinite loops.

For positive steps: iterates from start towards end (exclusive) by step increments. For negative steps: iterates from start towards end (exclusive) by step decrements.

Examples:

// Ascending with step 2
for i := range goter.Step(ctx, 0, 10, 2) {
	fmt.Println(i) // Prints: 0, 2, 4, 6, 8
}

// Descending with negative step
for i := range goter.Step(ctx, 10, 0, -3) {
	fmt.Println(i) // Prints: 10, 7, 4, 1
}

// Zero step produces no values (safe)
for i := range goter.Step(ctx, 0, 10, 0) {
	// This loop body never executes
}

func Substrings

func Substrings(ctx context.Context, s string, length int) iter.Seq[string]

Substrings creates an iterator that yields all substrings of a given length. The iterator slides through the string one character at a time.

Example:

ctx := context.Background()
text := "Hello"
for substr := range goter.Substrings(ctx, text, 3) {
	fmt.Printf("Substring: '%s'\n", substr)
	// Output:
	// Substring: 'Hel'
	// Substring: 'ell'
	// Substring: 'llo'
}

func Suffixes

func Suffixes(ctx context.Context, s string) iter.Seq[string]

Suffixes creates an iterator that yields all non-empty suffixes of a string. Suffixes are yielded in order of decreasing length.

Example:

ctx := context.Background()
text := "Hello"
for suffix := range goter.Suffixes(ctx, text) {
	fmt.Printf("Suffix: '%s'\n", suffix)
	// Output:
	// Suffix: 'Hello'
	// Suffix: 'ello'
	// Suffix: 'llo'
	// Suffix: 'lo'
	// Suffix: 'o'
}

func Take

func Take[T any](ctx context.Context, iterator iter.Seq[T], n int) iter.Seq[T]

Take creates an iterator that yields at most n elements from the source iterator. Stops early if the source iterator ends or context is cancelled.

Example:

ctx := context.Background()
numbers := goter.Count(ctx, 1000) // 0, 1, 2, ..., 999

for num := range goter.Take(ctx, numbers, 5) {
	fmt.Println(num) // 0, 1, 2, 3, 4 (only first 5)
}

func Ticker

func Ticker(ctx context.Context, startTime time.Time, duration time.Duration) iter.Seq[time.Time]

Ticker creates an iterator that yields timestamps at regular intervals. It starts from the next boundary aligned to the duration and continues indefinitely until the context is cancelled. The timer is properly cleaned up on context cancellation.

The startTime is truncated to the nearest duration boundary, then advanced by one duration to get the first timestamp. This ensures consistent timing regardless of when the iterator starts.

This is particularly useful for: - Creating periodic tickers - Scheduling regular tasks - Time-based event generation - Implementing cron-like functionality

Example:

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

startTime := time.Now()
interval := 1 * time.Second

for timestamp := range goter.Ticker(ctx, startTime, interval) {
	fmt.Printf("Tick at: %v\n", timestamp)
	// Process periodic task here
}

func Window

func Window[T any](ctx context.Context, iterator iter.Seq[T], size int) iter.Seq[[]T]

Window creates a sliding window iterator that yields slices of the specified size. Each window slides by one element. Stops when there aren't enough elements for a full window.

Example:

ctx := context.Background()
numbers := goter.Range(ctx, 0, 6) // 0, 1, 2, 3, 4, 5

for window := range goter.Window(ctx, numbers, 3) {
	fmt.Println(window) // [0 1 2], [1 2 3], [2 3 4], [3 4 5]
}

func Words

func Words(ctx context.Context, s string) iter.Seq[string]

Words creates an iterator that yields words from a string. Words are separated by whitespace characters.

Example:

ctx := context.Background()
text := "Hello   world\t\nfrom Go!"
for word := range goter.Words(ctx, text) {
	fmt.Printf("Word: '%s'\n", word)
	// Output:
	// Word: 'Hello'
	// Word: 'world'
	// Word: 'from'
	// Word: 'Go!'
}

func Wrap

func Wrap[ValueType any](ctx context.Context, iterator iter.Seq[ValueType]) iter.Seq[ValueType]

Wrap wraps an existing iterator with context support for graceful cancellation. When the context is cancelled, the iteration stops immediately. This allows for cooperative cancellation of long-running iterations without blocking indefinitely.

Example:

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

data := []int{1, 2, 3, 4, 5}
simpleIter := func(yield func(int) bool) {
	for _, v := range data {
		if !yield(v) {
			return
		}
	}
}

for v := range goter.Wrap(ctx, simpleIter) {
	fmt.Println(v) // Will stop after 5 seconds if iteration takes too long
}

func Wrap2

func Wrap2[KeyType any, ValueType any](ctx context.Context, iterator iter.Seq2[KeyType, ValueType]) iter.Seq2[KeyType, ValueType]

Wrap2 wraps an existing key-value iterator with context support for graceful cancellation. Similar to Wrap, but works with iter.Seq2 for key-value pairs like maps.

Example:

ctx := context.Background()
data := map[string]int{"a": 1, "b": 2, "c": 3}
mapIter := func(yield func(string, int) bool) {
	for k, v := range data {
		if !yield(k, v) {
			return
		}
	}
}

for k, v := range goter.Wrap2(ctx, mapIter) {
	fmt.Printf("%s: %d\n", k, v)
}

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL