Structured concurrency from The Go Programming Language code reimagined/reimplemented in Kotlin coroutines
fun gotlin(go): kotlin
Why?
Go's goroutines and Kotlin's coroutines have a lot in common (and only one letter different)!
While learning Kotlin I struggled a bit with understanding coroutines in a way that I didn't when learning goroutines.
When I learned about Kotlin's select
I realized I could fully
re-apply my goroutine knowledge. I don't have a Kotlin coroutine book on my shelf, but I do have "The Go Programming
Language"
So, for my own self-elucidation (and hopefully others as well!) I began rewriting the examples in Kotlin.
I found Kotlin coroutines online quite lacking, so hopefully this helps improve that by proxy.
- This is NOT production code. I don't do great error handling and the code is probably terrible.
- I'm still new to Kotlin. I did this as a part of learning Kotlin. See point #1
- Coroutines are available in Kotlin
via
kotlinx-coroutines-core
. Coroutines aren't a part of the core language like goroutines are in Go. - I first used http4k as a substitute for Go net/http for requests and server. Later on I started using Ktor
Of course: if you've got suggestions, please create Pull Requests!
- See the Coroutine extension pattern below
- Kotlin's Channels throw exceptions if read from after close. Go's channels return zero-value.
- Kotlin's
select
is implemented as a DSL and has some differences from Go'sselect
:- If multiple cases are valid, Kotlin biases toward the first whereas Go will pick at random.
- Kotlin's
select
doesn't have adefault
- Rather than using
object{}
which is akin to Go'sstruct{}{}
, Kotlin can instead useUnit
for channels that only process signals without any content. - Kotlin has
whileSelect
which replaces Go'sfor { select {
infinite-loop pattern.
I learned this pattern from: Kotlin Coroutines in Practice. In-fact, that talk directly inspired me to work on this.
import kotlin.coroutines.CoroutineContext
// Take a function...
fun fn() {
/* do fn stuff */
}
// ...and simply change the first line to the following
fun CoroutineContext.fn() = launch {
/* do fn stuff */
}
// ... and now you can call it within any coroutine scope and it will launch a coroutine
fun main() = runBlocking {
fn() // now this is semi-equivalent to `go fn()` in Go
}
- http4k reference
- Default map in Kotlin
- Go's Map operates like a default map where the default is the zero value of the map-value type
- Simple socket server in Kotlin
- Java Socket examples
- Kotlin TCP example
- Kotlin
use
keywordresource.use
auto-closes the resource after theuse
block
- Ktor
In no way do the authors of "The Go Programming Language" endorse this or this use.
These examples are licensed under a Creative
Commons Attribution-NonCommercial-ShareAlike 4.0 International License.