Go select vs Rust select! fairness and determinism
This tests runtime fairness in concurrent primitives. Contrast Go's pseudo-random case selection with Tokio's randomized default and its opt-in biased; top-down mode. Red flag: claiming Go uses source order or that Rust randomization is unavoidable.
WHAT THIS TESTS: This question probes your understanding of fairness and determinism trade-offs in concurrency primitives at the language-runtime boundary. Interviewers want to see if you know that Go baked a specific starvation-avoidance strategy into its select statement, and whether you understand that Tokio's select! macro provides a configurable default with an escape hatch for deterministic ordering. It also checks if you can articulate why randomization matters in a loop where branches are frequently ready.
A GOOD ANSWER COVERS: First, state that Go's select uses a uniform pseudo-random choice among all ready cases, which makes the textual order of cases irrelevant and prevents any single channel from starving others. Second, explain that Tokio's select! also randomizes the polling order by default to provide fairness when used in a loop. Third, highlight the key differentiator: Tokio accepts an optional biased; annotation at the start of the macro, which switches to strict top-down polling in source order, eliminating RNG overhead and enabling deterministic behavior when the programmer knows the polling order matters. Fourth, mention the risk of biased; mode: if earlier branches are always ready, later branches can starve. Fifth, note that Go offers no equivalent opt-in for deterministic select ordering; randomness is mandatory.
COMMON WRONG ANSWERS: A major red flag is asserting that Go evaluates select cases in declaration order, which betrays a lack of familiarity with the Go spec. Another is claiming that Tokio's select! is purely deterministic or that it always polls in source order without mentioning the biased; override. Some candidates incorrectly state that Rust's default randomization is a performance bug rather than an intentional fairness mechanism. Confusing async message passing with POSIX select or epoll behavior is also a signal that the candidate is mixing abstraction layers.
LIKELY FOLLOW-UPS: An interviewer might ask when you would use biased; in production, expecting an answer about hot loops where RNG overhead is measurable or where futures interact in ways that make known polling order significant. They might also ask how you would implement deterministic prioritization in Go given that its select is always randomized, leading to a discussion of auxiliary data structures or separate goroutines. Another follow-up is whether Tokio select! branches run in parallel; the answer is that they run concurrently on the current task but not in parallel, so blocking one branch blocks the rest unless you spawn them into separate tasks.
ONE CONCRETE EXAMPLE: Imagine a telemetry loop with three Tokio branches: a high-priority alert channel, a low-priority metrics channel, and a shutdown signal. With the default randomized select!, a burst of metrics could occasionally delay an alert by one poll iteration. If latency variance is unacceptable and alerts are rare, you might use biased; to check the alert branch first, accepting that a continuous flood of alerts could starve metrics. In Go, the same scenario would require a separate goroutine or a priority queue because select itself cannot be biased toward the alert channel.
Read the original → docs.rs
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.