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.
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.
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.
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.
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.
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.
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.
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
List all Go tutorials.