ZetCode

Golang slices.Collect

last modified June 21, 2026

This tutorial explains how to use the slices.Collect function in Go. We cover collecting values from iterators into slices with practical examples.

The slices.Collect function collects all values from an iter.Seq[E] iterator into a new slice and returns it. Its signature is:

func Collect[E any](seq iter.Seq[E]) []E

The function was introduced in Go 1.23 together with the iterator support added to the language. It pairs naturally with iterator-producing functions such as maps.Keys, maps.Values, and slices.Values.

Collecting Map Keys

maps.Keys returns an iter.Seq[K] over the keys of a map. slices.Collect materialises those keys into a slice.

collect_keys.go
package main

import (
    "fmt"
    "maps"
    "slices"
)

func main() {
    m := map[string]int{
        "one":   1,
        "two":   2,
        "three": 3,
    }

    keys := slices.Collect(maps.Keys(m))
    slices.Sort(keys)

    fmt.Println(keys) // [one three two]
}

Because map iteration order is undefined, we sort the resulting slice before printing so the output is deterministic.

Collecting Map Values

maps.Values produces an iterator over map values. We collect those values into a slice the same way.

collect_values.go
package main

import (
    "fmt"
    "maps"
    "slices"
)

func main() {
    scores := map[string]int{
        "Alice":   92,
        "Bob":     85,
        "Charlie": 78,
    }

    vals := slices.Collect(maps.Values(scores))
    slices.Sort(vals)

    fmt.Println(vals) // [78 85 92]
}

The values are collected in an arbitrary order, then sorted for a predictable result.

Round-trip Through an Iterator

slices.Values converts a slice into an iter.Seq[E] iterator. Passing that iterator to slices.Collect produces a shallow copy of the original slice.

collect_roundtrip.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    original := []int{10, 20, 30, 40, 50}

    copy := slices.Collect(slices.Values(original))

    fmt.Println(copy)          // [10 20 30 40 50]
    fmt.Println(&original[0] != ©[0]) // true – different backing arrays
}

The two slices hold the same values but point to independent backing arrays, so modifying one does not affect the other.

Custom Iterator

Any function with the signature func(yield func(E) bool) satisfies iter.Seq[E]. We can write our own generators and collect their output directly into a slice.

collect_custom.go
package main

import (
    "fmt"
    "iter"
    "slices"
)

// integers yields consecutive integers in [start, end).
func integers(start, end int) iter.Seq[int] {
    return func(yield func(int) bool) {
        for i := start; i < end; i++ {
            if !yield(i) {
                return
            }
        }
    }
}

func main() {
    nums := slices.Collect(integers(1, 6))
    fmt.Println(nums) // [1 2 3 4 5]
}

The generator respects early termination by checking the return value of yield and stopping when it is false.

Filtering with a Custom Iterator

We can compose iterators. A filter adapter wraps any iter.Seq[E] and forwards only elements that satisfy a predicate. slices.Collect then gathers the surviving elements.

collect_filter.go
package main

import (
    "fmt"
    "iter"
    "slices"
)

func filter[E any](seq iter.Seq[E], keep func(E) bool) iter.Seq[E] {
    return func(yield func(E) bool) {
        for v := range seq {
            if keep(v) {
                if !yield(v) {
                    return
                }
            }
        }
    }
}

func main() {
    nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

    even := slices.Collect(filter(slices.Values(nums), func(n int) bool {
        return n%2 == 0
    }))

    fmt.Println(even) // [2 4 6 8 10]
}

The filter function is generic and works with any element type. The result is a new slice containing only the even numbers from the original.

Collecting from a Channel

A channel can be wrapped in an iter.Seq adapter so that its values are consumable by slices.Collect.

collect_channel.go
package main

import (
    "fmt"
    "iter"
    "slices"
)

func fromChan[E any](ch <-chan E) iter.Seq[E] {
    return func(yield func(E) bool) {
        for v := range ch {
            if !yield(v) {
                return
            }
        }
    }
}

func main() {
    ch := make(chan int, 5)
    for _, v := range []int{10, 20, 30, 40, 50} {
        ch <- v
    }
    close(ch)

    nums := slices.Collect(fromChan(ch))
    fmt.Println(nums) // [10 20 30 40 50]
}

The channel must be closed before (or during) iteration so the adapter knows when to stop. The collected slice preserves the channel's send order.

Practical Example: Struct Field Extraction

A common task is extracting one field from a slice of structs. We write a generic mapSeq adapter that transforms each element of an iterator, then collect the result.

collect_structs.go
package main

import (
    "fmt"
    "iter"
    "slices"
)

type Person struct {
    Name string
    Age  int
}

func mapSeq[In, Out any](seq iter.Seq[In], f func(In) Out) iter.Seq[Out] {
    return func(yield func(Out) bool) {
        for v := range seq {
            if !yield(f(v)) {
                return
            }
        }
    }
}

func main() {
    people := []Person{
        {"Alice", 25},
        {"Bob", 30},
        {"Charlie", 17},
    }

    names := slices.Collect(mapSeq(slices.Values(people), func(p Person) string {
        return p.Name
    }))

    fmt.Println(names) // [Alice Bob Charlie]
}

mapSeq is a reusable transform adapter. It converts each Person to a string by extracting the Name field, and slices.Collect materialises those strings into a slice.

Source

Go slices.Collect documentation

This tutorial covered the slices.Collect function in Go with examples showing how to collect map keys and values, custom iterators, filtered sequences, channel values, and struct field extraction.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Go tutorials.