Inversion of control

Iteration using anonymous callbacks

A downside to using generators is that the generator can only do any resource cleanup when it reaches the end of the sequence. If the client code doesn't consume all possible values, cleanup other than via garbage collection requires the client to make further calls.

An alternative is for the client code to provide a callback and have it explicitly indicate if it does not want any additional values. This is made particularly straightforward by Go's first class functions:

package main

import "fmt"

func generateInts(max int, handler func(value int) (wantMore bool)) {
    var current int = 1
    // Pre-iteration resource allocation goes here
    for current < max {
        if !handler(current) {
            // Resource clean-up for mid-iteration stop goes here
            return
        }
        current++
    }
    // End of iteration resource clean-up goes here
}

func main() {
    generateInts(10, func(value int) (wantMore bool) {
        fmt.Printf("Iteration value %v\n", value)
        if value == 5 {
            // Stop when we reach 5
            return false
        }
        return true
    })
}

Run in Playground

In our call to generateInts we pass an anynmous function that will be called for each iteration, or until it requests iteration to be stopped.

The handler function definition can be extended to provide an indicator that the value being given is the last one in the sequence if this is required.

A good real world example of using this technique is for SQL Queries where both resources (closing the query object) and final error checking are required.

Last Modified: Sun, 10 Jan 2016 22:36:54 CET

Made with PubTal 3.5

Copyright 2021 Colin Stewart

Email: colin at owlfish.com