Select in Kotlin

Kotlin’s select expression lets you wait on multiple channel operations. Combining coroutines and channels with select is a powerful feature of Kotlin.

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

suspend fun main() = coroutineScope {
    // For our example we'll select across two channels.
    val c1 = Channel<String>()
    val c2 = Channel<String>()

    // Each channel will receive a value after some amount
    // of time, to simulate e.g. blocking RPC operations
    // executing in concurrent coroutines.
    launch {
        delay(1000)
        c1.send("one")
    }
    launch {
        delay(2000)
        c2.send("two")
    }

    // We'll use `select` to await both of these values
    // simultaneously, printing each one as it arrives.
    repeat(2) {
        select<Unit> {
            c1.onReceive { msg1 ->
                println("received $msg1")
            }
            c2.onReceive { msg2 ->
                println("received $msg2")
            }
        }
    }

    // Close the channels
    c1.close()
    c2.close()
}

We receive the values “one” and then “two” as expected.

$ kotlinc -cp kotlinx-coroutines-core.jar select.kt -include-runtime -d select.jar
$ kotlin -cp kotlinx-coroutines-core.jar:select.jar SelectKt
received one
received two

Note that the total execution time is only ~2 seconds since both the 1 and 2 second delays execute concurrently.

In this Kotlin version:

  1. We use kotlinx.coroutines library for coroutines and channels.
  2. The main function is marked as suspend and wrapped in coroutineScope to allow the use of coroutines.
  3. Instead of goroutines, we use Kotlin’s launch to start new coroutines.
  4. We use Channel from kotlinx.coroutines.channels instead of Go’s built-in channels.
  5. The select statement is replaced with Kotlin’s select function from kotlinx.coroutines.selects.
  6. We use delay instead of Sleep for pausing execution.
  7. After the operations, we close the channels explicitly.

This example demonstrates how Kotlin can achieve similar concurrent behavior to Go, using coroutines and channels.