It’s great that they identified this (incredibly common) pain point and introduced a way to solve it, but I can’t help being disappointed.
Reading the examples I found myself thinking, “that looks like a really useful pattern, I should bookmark this so I can adopt it whenever I write code like that.”
The fact that I’m considering bookmarking a blog post about complex boilerplate that I would want to use 100% of the times when it’s applicable is a huge red flag and is exactly why people complain about Go.
It feels like you’re constantly fighting the language: having to add error handling boilerplate everywhere and having to pass contexts everywhere (more boilerplate). This is the intersection of those two annoyances so it feels especially annoying (particularly given the nuances/footguns the author describes).
They say the point is that Go forces you to handle errors but 99% of the time that means just returning the error after possibly wrapping it. After a decade of writing Go I still don’t have a good rule of thumb for when I should wrap an error with more info or return it as-is.
I hope someday they make another attempt at a Go 2.0.
Context cancellation (and it's propagation) is one of the best features in Go.
Is there any equivalent in major popular languages like Python, Java, or JS of this?
ZIO in Scala tracks this sort of thing except you don't have to remember to pass around or select on the ctx (it's just part of the fibre/"goroutine"); if it's cancelled, the fibre and its children just stops the next time it yields (so e.g. if it "selects" on anything or does any kind of IO).
Python async tasks can be cancelled. But, I don't think you can attach must context to the cancel (I think you can pass a text message), so it would seem the argument of what go suffered from would apply.
(I also think there's some wonkiness with and barriers to understanding Python's implementation that I don't think plagues Go to quite the same extent.)
All mainstream languages have it in one or more forms (either direct task I/O cancellation, or cancellation tokens or I/O polling that can include synthetic events) since otherwise several I/O patterns are impossible
C# has CancellationToken, but it’s just for canceling operations, not a general purpose context.
in JS, signals and AbortController can replicate some of the functionality but it's far less ergonomic than Go.
https://github.com/ggoodman/context provides nice helpers that brings the DX a bit closer to Go.
one of the reasons why i love writing control planes in Go.
Java's Virtual Threads (JVM 21) + the Structured Concurrency primitives (not sure exactly what's available in Java 21+) do this natively.
Also, a sibling poster mentioned ZIO/Scala which does the Structured Concurrency thing out of the box.
Kotlin Coroutine's structured concurrency. Cancelling a parent automatically cancels child jobs, unless explicitly handled not to. https://kotlinlang.org/docs/coroutines-basics.html
Not really, since they don't have `select`
There's a stop_token in some Microsoft C++ library but it's not nearly as convenient to interrupt a blocking operation with it.