Goroutine-Style Concurrency
debt(d9/e5/b5/t7)
Closest to 'silent in production until users hit it' (d9). The detection_hints field explicitly states 'automated: no'. Misuse of goroutines/fibers — such as uncaught panics silently dying, goroutine leaks, or PHP fibers not scheduling without an event loop — produces no compile-time or lint-time warnings. Issues only surface at runtime, often under load or in production scenarios.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix mentions adopting Revolt or Swoole for PHP, or restructuring Go code to use channels and proper error handling. This isn't a single-line swap — integrating an event loop (Revolt/Swoole) or retrofitting error handling across goroutine/coroutine boundaries touches multiple call sites and architectural decisions, but is contained within a single component or service rather than being fully cross-cutting.
Closest to 'persistent productivity tax' (b5). The applies_to scope is cli and queue-worker contexts, meaning this choice affects meaningful but bounded parts of the codebase. Once a fiber-based event loop (Swoole, Revolt) or goroutine architecture is adopted, every future maintainer working in those contexts must understand the concurrency model, error propagation patterns, and scheduling semantics — a persistent but not system-defining tax.
Closest to 'serious trap (contradicts how a similar concept works elsewhere)' (t7). The misconception field directly states: 'Goroutines are threads — they're scheduled by the Go runtime, not the OS.' Developers familiar with OS threads or POSIX threads will assume 1:1 mapping and reason incorrectly about scheduling, memory, and cost. Similarly, the common_mistake that PHP Fibers need an explicit event loop contradicts how goroutines appear to work automatically, making cross-language reasoning treacherous. This is a serious trap that contradicts well-established mental models from thread-based concurrency.
TL;DR
Explanation
Goroutine: a lightweight, cooperatively/preemptively scheduled unit of execution in Go. Cost: ~2KB initial stack (vs ~1MB for OS thread). Go scheduler: M:N threading — maps M goroutines onto N OS threads. Similar concepts: PHP Fibers (cooperative, same thread), Swoole coroutines (cooperative, event-loop based), Python asyncio tasks, Kotlin coroutines, Java virtual threads (Project Loom). Benefits: thousands of concurrent tasks with small memory footprint. Communication: Go uses channels (CSP model). PHP equivalent: Swoole coroutines + channels, or Revolt Fiber-based async. The PHP Fiber (8.1) is the primitive; frameworks build on top.
Common Misconception
Why It Matters
Common Mistakes
- Expecting PHP Fibers to schedule automatically — they need an event loop (Revolt, Swoole) to be useful.
- Treating goroutines as free — thousands are cheap, millions have overhead.
- Not handling goroutine/coroutine panics/errors — uncaught errors silently die.
Code Examples
// PHP Fiber without event loop — doesn't help:
$fiber = new Fiber(function() { doWork(); });
$fiber->start(); // Just runs synchronously
// With Revolt event loop:
use Revolt\EventLoop;
EventLoop::queue(function() { doWork1(); });
EventLoop::queue(function() { doWork2(); }); // Runs concurrently
EventLoop::run();