conc
Better structured concurrency for go
A Go library that makes running concurrent tasks safe and readable, automatically prevents goroutine leaks, catches panics with stack traces, and replaces messy concurrency boilerplate with clean structured building blocks.
conc is a Go library that makes it safer and easier to write code that does multiple things at the same time. In Go, concurrent work is handled by goroutines, which are lightweight threads the runtime manages. The standard library provides basic tools for working with goroutines, but getting them right requires a lot of careful boilerplate. conc provides a cleaner set of building blocks that handle the most common failure modes automatically.
The three main problems conc addresses are goroutine leaks, unhandled panics, and hard-to-read concurrent code. A goroutine leak happens when a goroutine is started but nothing ensures it ever finishes. A panic inside a goroutine that has no handler will crash the entire program. And concurrent code written with raw goroutines tends to accumulate error-handling scaffolding that obscures the actual logic.
conc enforces the idea that every goroutine should have an owner, and that owner is always responsible for waiting until the goroutine finishes. This is called structured concurrency. The core type is a WaitGroup, similar to the one in Go's standard library but with additional guarantees. If any goroutine in the group panics, the panic is caught and re-raised (with a preserved stack trace) when the owner calls Wait.
The library also provides a Pool for running a limited number of tasks concurrently, a ResultPool for collecting return values from concurrent tasks, error-aware and context-aware variants for cancellation on failure, a Stream type for processing ordered sequences in parallel, and iterator helpers for mapping or looping over slices concurrently.
Installation is a single command: go get github.com/sourcegraph/conc. The package is from Sourcegraph, a code search company, and was extracted from patterns they found themselves using repeatedly in their own Go codebase.
Where it fits
- Run a fixed number of tasks in parallel in Go and safely wait for all of them to finish without goroutine leaks.
- Collect return values or errors from concurrent Go tasks without losing panics or needing complex error channels.
- Process a large slice of items in parallel using conc's iterator helpers, with automatic panic recovery.