Golang slices.Chunk
last modified June 21, 2026
This tutorial explains how to use the slices.Chunk function in Go.
We cover iterating over successive non-overlapping chunks of a slice with
practical examples.
The slices.Chunk function returns an iterator (iter.Seq[S])
that yields successive non-overlapping sub-slices of length n.
Its signature is:
func Chunk[Slice ~[]E, E any](s Slice, n int) iter.Seq[Slice]
The function was introduced in Go 1.23. Every chunk except possibly the last
has exactly n elements. The chunks are sub-slices of the original,
so they share the same backing array.
Basic slices.Chunk Example
The simplest use iterates over chunks with a for range loop.
Here we split a slice of six integers into chunks of size 2.
package main
import (
"fmt"
"slices"
)
func main() {
numbers := []int{1, 2, 3, 4, 5, 6}
for chunk := range slices.Chunk(numbers, 2) {
fmt.Println(chunk)
}
}
The iterator yields each sub-slice in order. Because the length (6) is evenly divisible by the chunk size (2), all three chunks have equal length.
Uneven Chunk Sizes
When the slice length is not evenly divisible by the chunk size, the last chunk contains the remaining elements.
package main
import (
"fmt"
"slices"
)
func main() {
letters := []string{"a", "b", "c", "d", "e"}
for chunk := range slices.Chunk(letters, 2) {
fmt.Printf("chunk: %v\n", chunk)
}
}
Five elements chunked by 2 produce two full chunks and one remainder chunk of length 1.
Collecting All Chunks into a Slice
When you need all chunks at once — for example to index into them — use
slices.Collect to materialise the iterator into a [][]E.
package main
import (
"fmt"
"slices"
)
func main() {
data := []int{10, 20, 30, 40, 50, 60, 70}
chunks := slices.Collect(slices.Chunk(data, 3))
fmt.Println("number of chunks:", len(chunks))
fmt.Println("first chunk: ", chunks[0])
fmt.Println("last chunk: ", chunks[len(chunks)-1])
}
slices.Collect drains the iterator and returns a
[][]int. The last chunk has only one element because 7 is not
divisible by 3.
Chunk Size Larger Than the Slice
If the chunk size is equal to or greater than the slice length, the iterator yields exactly one chunk containing all elements.
package main
import (
"fmt"
"slices"
)
func main() {
data := []float64{1.1, 2.2, 3.3}
for chunk := range slices.Chunk(data, 10) {
fmt.Println(chunk) // [1.1 2.2 3.3]
}
}
A chunk size of 10 is larger than the three-element slice, so the loop body executes once with the entire slice as the single chunk.
Working with Structs
slices.Chunk works with any element type, including custom structs.
package main
import (
"fmt"
"slices"
)
type Person struct {
Name string
Age int
}
func main() {
people := []Person{
{"Alice", 25},
{"Bob", 30},
{"Charlie", 17},
{"Diana", 22},
{"Eve", 28},
}
i := 1
for chunk := range slices.Chunk(people, 2) {
fmt.Printf("group %d:\n", i)
for _, p := range chunk {
fmt.Printf(" %s (%d)\n", p.Name, p.Age)
}
i++
}
}
Each chunk is a sub-slice of the original people slice. The struct
values are not copied beyond the sub-slice header.
group 1: Alice (25) Bob (30) group 2: Charlie (17) Diana (22) group 3: Eve (28)
Chunks Share the Backing Array
Because chunks are sub-slices, modifying an element inside a chunk modifies the original slice. This is worth keeping in mind when processing chunks concurrently or after the fact.
package main
import (
"fmt"
"slices"
)
func main() {
nums := []int{1, 2, 3, 4, 5, 6}
for chunk := range slices.Chunk(nums, 2) {
chunk[0] = 0 // modifies the original slice
}
fmt.Println(nums) // [0 2 0 4 0 6]
}
Setting the first element of each chunk to zero also zeroes every other element of the original slice, confirming the shared backing array.
Practical Example: Batch Processing
A common use-case is processing a large dataset in fixed-size batches to limit memory pressure or API call size.
package main
import (
"fmt"
"slices"
)
func insertBatch(batch []int) {
fmt.Printf("inserting %d records: %v\n", len(batch), batch)
}
func main() {
records := make([]int, 10)
for i := range records {
records[i] = (i + 1) * 10
}
const batchSize = 3
for batch := range slices.Chunk(records, batchSize) {
insertBatch(batch)
}
}
The insertBatch function simulates inserting a batch of records
into a database or an external system.
The iterator produces batches on demand, so only one chunk is in play at a time. No up-front allocation of a slice-of-slices is needed.
Source
This tutorial covered the slices.Chunk function in Go with examples
showing basic iteration, uneven sizes, collecting chunks, struct slices, shared
backing arrays, and batch processing.
Author
List all Go tutorials.