Early return and goroutine leak

At work, a common mistake I notice when reviewing candidates’ home assignments is how they wire goroutines to channels and then return early. The pattern usually looks like this: start a few goroutines each goroutine sends a result to its own unbuffered channel in the main goroutine, read from those channels one by one if any read contains an error, return early The trap is the early return. With an unbuffered channel, a send blocks until a receiver is ready. If you return before reading from the remaining channels, the goroutines writing to them block forever. That’s a goroutine leak. ...

September 7, 2025

Limit goroutines with buffered channels

I was cobbling together a long-running Go script to send webhook messages to a system when some events occur. The initial script would continuously poll a Kafka topic for events and spawn new goroutines to make HTTP requests to the destination. This had two problems: It could create unlimited goroutines if many events arrived quickly It might overload the destination system by making many concurrent requests In Python, I’d use just asyncio.Semaphore to limit concurrency. I’ve previously written about this here. Turns out, in Go, you could do the same with a buffered channel. Here’s how the naive version looks: ...

August 23, 2023