Custom iterators

October 6, 2025

Until recently, custom iterators were probably the most common way to iterate over a list of elements that might trigger an error. Several examples exist in the standard library. Perhaps the most well known would be the sql.Rows type, which provides (among others), the following methods:

These four methods are pretty standard, in any custom iterator implementation, though Scan() will typically be replaced with an implementation-specific method to process the current result, and in some cases Err() and Close() may be combined.

Let’s see what this might look like for our orders example:

orders, err := db.Orders(ctx, userID)
if err != nil {
	return err
}
defer orders.Close() // Ensure that the iterator is cleaned up, even in case of early return
for orders.Next() {
	order, err := orders.Process()
	if err != nil {
		return err
	}
	/* Do something with each order */
}
if err := orders.Err(); err != nil {
	return err
}

This approach is infinitely flexible. It allows exposing specific errors at various places (in the example, four places: db.Orders, orders.Process(), orders.Err(), and orders.Close()). And it allows the addition of an arbitrary number of other methods, which might be used to expose per-item or per-query metadata, or to do different types of processing.


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Get daily content like this in your inbox!

Subscribe