ZetCode

Golang slices.All

last modified June 21, 2026

This tutorial explains how to use the slices.All function in Go. We cover iterating over index-value pairs of a slice with practical examples.

The slices.All function returns an iterator that yields the index and value of every element in a slice. Its signature is:

func All[Slice ~[]E, E any](s Slice) iter.Seq2[int, E]

The function was introduced in Go 1.23. It is the indexed counterpart of slices.Values: where slices.Values yields only values, slices.All yields (index, value) pairs — similar to enumerate in Python.

Basic slices.All Example

The simplest use iterates over all elements with their indices using a for range loop.

basic_all.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    fruits := []string{"apple", "banana", "cherry"}

    for i, v := range slices.All(fruits) {
        fmt.Printf("%d: %s\n", i, v)
    }
}

The loop variable i receives the index and v the value, following the same two-variable form used when ranging directly over a slice.

Difference Between slices.All and slices.Values

slices.Values yields only values (iter.Seq[E]), while slices.All yields index-value pairs (iter.Seq2[int, E]).

all_vs_values.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    nums := []int{10, 20, 30}

    fmt.Println("slices.Values:")
    for v := range slices.Values(nums) {
        fmt.Println(v)
    }

    fmt.Println("slices.All:")
    for i, v := range slices.All(nums) {
        fmt.Printf("[%d] = %d\n", i, v)
    }
}

Use slices.Values when the index is not needed, and slices.All when you need to know the position of each element.

Early Termination

The iterator stops early if the loop body executes a break. This is efficient because no further elements are visited after the break.

early_break.go
package main

import (
    "fmt"
    "slices"
)

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

    // Find the index of the first value greater than 5.
    found := -1
    for i, v := range slices.All(nums) {
        if v > 5 {
            found = i
            break
        }
    }

    fmt.Println("first index > 5:", found) // 1
}

The loop breaks as soon as the value 7 (index 1) is found, without visiting the remaining elements.

Working with Structs

slices.All works with any element type, including custom structs.

struct_all.go
package main

import (
    "fmt"
    "slices"
)

type Person struct {
    Name string
    Age  int
}

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

    for i, p := range slices.All(people) {
        fmt.Printf("%d: %s, age %d\n", i, p.Name, p.Age)
    }
}

The index makes it easy to refer back to the original slice position when processing or updating elements.

Collecting Index-Value Pairs

Because slices.All returns an iter.Seq2, it cannot be passed directly to slices.Collect (which expects iter.Seq). To materialise the pairs, collect them manually into a struct slice.

collect_pairs.go
package main

import (
    "fmt"
    "slices"
)

type IndexedValue[E any] struct {
    Index int
    Value E
}

func main() {
    letters := []string{"x", "y", "z"}

    var pairs []IndexedValue[string]
    for i, v := range slices.All(letters) {
        pairs = append(pairs, IndexedValue[string]{i, v})
    }

    fmt.Println(pairs)
    // [{0 x} {1 y} {2 z}]
}

The generic IndexedValue struct holds the index and value together, producing a snapshot of the enumerated slice.

Passing the Iterator to a Function

An iter.Seq2[int, E] value can be stored or passed to helper functions, enabling reusable iteration logic.

iterator_arg.go
package main

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

func printIndexed[E any](seq iter.Seq2[int, E]) {
    for i, v := range seq {
        fmt.Printf("  [%d] %v\n", i, v)
    }
}

func main() {
    scores := []int{88, 74, 95, 61}

    fmt.Println("scores:")
    printIndexed(slices.All(scores))
}

The helper accepts any iter.Seq2[int, E], so it works with slices.All, maps.All, or any custom iterator with the same signature.

Practical Example: Annotating a Report

slices.All is convenient when building output that needs one-based row numbers alongside the data.

report.go
package main

import (
    "fmt"
    "slices"
)

type Product struct {
    Name  string
    Price float64
}

func main() {
    products := []Product{
        {"Widget", 9.99},
        {"Gadget", 24.50},
        {"Doohickey", 4.75},
    }

    fmt.Printf("%-4s %-12s %s\n", "#", "Name", "Price")
    fmt.Println("----------------------------")
    for i, p := range slices.All(products) {
        fmt.Printf("%-4d %-12s $%.2f\n", i+1, p.Name, p.Price)
    }
}

Adding 1 to the zero-based index gives a natural row number in the report without maintaining a separate counter variable.

$ go run report.go
#    Name         Price
----------------------------
1    Widget       $9.99
2    Gadget       $24.50
3    Doohickey    $4.75

Source

Go slices.All documentation

This tutorial covered the slices.All function in Go with examples showing basic iteration, comparison with slices.Values, early termination, struct slices, collecting pairs, passing iterators, and report generation.

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.