go
33 lines · 6 steps
Splitting a slice into batches in Go
A generic Chunk helper divides any slice into fixed-size groups, and ProcessInBatches runs a callback over each one.
Explained by
highlit
1package batch
2
3import "fmt"
4
5func Chunk[T any](items []T, size int) ([][]T, error) {
6 if size <= 0 {
7 return nil, fmt.Errorf("chunk size must be positive, got %d", size)
8 }
9
10 chunks := make([][]T, 0, (len(items)+size-1)/size)
11 for start := 0; start < len(items); start += size {
12 end := start + size
13 if end > len(items) {
14 end = len(items)
15 }
16 chunks = append(chunks, items[start:end:end])
17 }
18 return chunks, nil
19}
20
21func ProcessInBatches[T any](items []T, size int, fn func(batch []T) error) error {
22 chunks, err := Chunk(items, size)
23 if err != nil {
24 return err
25 }
26
27 for i, batch := range chunks {
28 if err := fn(batch); err != nil {
29 return fmt.Errorf("batch %d/%d failed: %w", i+1, len(chunks), err)
30 }
31 }
32 return nil
33}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Type parameters let one function batch slices of any element type without duplication.
- 2Pre-sizing a slice with the ceiling division of length over size avoids repeated reallocation.
- 3Wrapping errors with %w preserves the original cause while adding batch context.
Related explainers
go
package middleware import ( "errors"
Capping request body size in Gin
middleware
request limits
error handling
Intermediate
5 steps
php
<?php namespace App\Console\Commands;
How a database backup command works in Laravel
artisan-command
shell-process
error-handling
Intermediate
8 steps
typescript
import { Controller } from '@nestjs/common'; import { MessagePattern, Payload,
Manual RabbitMQ acks in a NestJS controller
microservices
message-queue
acknowledgement
Intermediate
8 steps
rust
use std::convert::TryFrom; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum HttpStatus {
Converting HTTP codes with TryFrom in Rust
enums
error-handling
trait-implementation
Intermediate
8 steps
rust
use chrono::NaiveDate; use serde::{Deserialize, Deserializer}; #[derive(Debug, Deserialize)]
Custom date parsing with serde in Rust
serde
deserialization
csv-parsing
Intermediate
7 steps
python
import uuid from pathlib import Path from fastapi import APIRouter, File, Form, HTTPException, UploadFile
Handling multipart file uploads in FastAPI
file-upload
validation
multipart-form
Intermediate
6 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/splitting-a-slice-into-batches-in-go-explained-go-5ae3/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.