Go Channel Deadlock Visualizer

Write a few goroutines and channels in the grammar below and this explores every interleaving of them. A deadlock comes with the shortest path to it and what each goroutine is stuck on; no deadlock means none is reachable, because the whole state space was walked. Anything it cannot decide it calls undecided.

Nothing you paste is transmitted. There is no endpoint behind this page: the Go that explores the state space is compiled to WebAssembly and runs in this tab, so what you write never leaves the browser.

The input is a small language, not Go

This is the whole reason the page can be honest about its answers. Deciding whether real Go can deadlock is not possible in general — loops, conditionals, recursion and channels made at run time put the state space beyond any finite search — so a tool that accepted Go source could only ever approximate, and an approximation that says “no deadlock” is worse than no tool at all.

So the language here has no loops, no conditionals other than select, no values and no function calls. What is left is exactly the part of a program that can deadlock. The state space is finite by construction, every interleaving is explored, and the answer is a proof rather than a sample.

Anything outside the grammar is refused with a line number. It is never quietly reinterpreted into something nearby.

Start from one of these

    The grammar

    Published in full, because the parser refuses everything outside it. This block is the same string the tool itself checks against, so the two cannot drift apart.

    
    
    

    The semantics it models, and nothing more

    • A send on an unbuffered channel blocks until a receiver is ready, and the two proceed together as one step.
    • A send on a buffered channel blocks only while the buffer is full.
    • A receive blocks while the buffer is empty and the channel is open.
    • A receive from a closed channel never blocks: it drains the buffer and then returns immediately, for ever.
    • A send on a closed channel panics. Closing a closed channel panics.
    • The program ends when main returns, whatever the other goroutines are doing. It deadlocks when main has not returned and nothing at all can move.

    It does not model scheduling order, GOMAXPROCS, timing, or which of several ready goroutines the runtime would pick. None of those is a documented guarantee, so an answer resting on one would be a guess. Every interleaving is explored instead, and the result says which outcomes are reachable.

    What each verdict means

    No deadlock is a proof, not a search that came up empty: the whole state space was walked and none of it deadlocks. Deadlock on every execution means there is no way through. Deadlock on some executions is the worst kind to have in real code — it depends on scheduling, so it passes in testing and fails in production.

    Undecided means the walk hit its state budget and stopped. It has not seen every execution, so it cannot say there is no deadlock, and it does not pretend otherwise. That substitution — reporting an incomplete search as safety — is the one thing this page must never do.

    Why the examples can be trusted

    Every example in the library above also exists as a real Go program in the repository, and the test suite compiles and runs each one on every build. The verdict shown here has to match what the Go runtime actually did — a deadlock, a panic, or a clean exit. An example the runtime contradicts fails the build.

    That check is what stands between this page and a confident wrong answer. A model of channel semantics is easy to write and easy to get subtly wrong, and every such mistake renders as something entirely plausible.

    A cycle is one shape of deadlock, not the definition

    When the goroutines are waiting on each other in a ring, the ring is named. But a single goroutine waiting on a channel nothing will ever touch is a deadlock with no cycle at all, and so are two goroutines stuck on unrelated channels. Where there is no cycle the page says so rather than staying quiet, because “no cycle” and “no deadlock” are very different findings.

    The other tools