Range Over Channels in Kotlin

In a previous example, we saw how for and in provide iteration over basic data structures. We can also use this syntax to iterate over values received from a channel.

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*

fun main() = runBlocking {
    // We'll iterate over 2 values in the `queue` channel.
    val queue = Channel<String>(2)
    queue.send("one")
    queue.send("two")
    queue.close()

    // This `for` loop iterates over each element as it's
    // received from `queue`. Because we closed the
    // channel above, the iteration terminates after
    // receiving the 2 elements.
    for (elem in queue) {
        println(elem)
    }
}

When you run this program, you’ll see:

one
two

This example also showed that it’s possible to close a non-empty channel but still have the remaining values be received.

In Kotlin, we use coroutines and channels to achieve similar functionality to Go’s goroutines and channels. The Channel class from the kotlinx.coroutines library provides a way to transfer a stream of values between coroutines.

We create a channel with a capacity of 2, send two values to it, and then close it. The for loop then iterates over the channel, receiving and printing each value. The loop automatically terminates when the channel is closed and all values have been received.

Note that in Kotlin, we need to use the runBlocking coroutine builder to create a coroutine scope in which we can use suspending functions like send and receive from channels.