Control Flow
Go keeps its set of control statements deliberately small: one if, one for, one switch, and the panic/recover pair for exceptional situations. Parentheses around conditions are not used, braces are always mandatory, and for is the language's only loop form: there is no while or do-while, everything is expressed through it.
Under that simplicity sit the differences interviews probe at the junior level: if and switch can carry an init statement with its own scope; a Go switch does not fall through between cases by default (you need an explicit fallthrough); range hands back pairs like "index, value" and reuses the loop variable; and recover works only inside a deferred function. This topic walks the flow of execution layer by layer — from branching to catching a panic.
Topic map
- Conditions:
if/else—if/else/else ifwith no parentheses around the condition and mandatory{}; the optional init statementif x := f(); x > 0 {…}lives only inside theif. - The
forloop — Go's only loop in three forms (C-style three-clause,for condinstead ofwhile, infinitefor {});break/continueand labels. switch— an expression switch with multiple values percase, no implicit fallthrough (fallthroughis explicit), the expressionlessswitch {}as anif-elsechain, and an optional init statement.range— iterate over a slice/array (index, value), amap(key, value), a string (byte index, rune), and a channel (received value);_drops what you do not need.panicandrecover—panicunwinds the stack, running deferred functions;recovercatches a panic only insidedefer; this is for exceptional cases, not for ordinary errors.
Common mistakes and traps
| Mistake | Consequence |
|---|---|
Writing if (cond) {…} with parentheses, like in C | The parentheses are redundant and not idiomatic; gofmt won't remove them, but a linter will flag it |
Dropping {} for a one-line if | Does not compile — braces are always mandatory in Go |
Using the variable from if x := f(); … after the if | x is visible only inside the if/else; outside it is a compile error |
Expecting one case to fall through into the next, as in C | A Go case does not fall through by default; you need an explicit fallthrough |
Putting break at the end of every case out of habit | The break is redundant — Go exits the switch itself after a case |
Taking the address of a range loop variable and keeping it | The variable is reused across iterations — every pointer ends up at the same value |
Calling recover() directly in the function body, not in a defer | Outside a deferred function recover returns nil and does not stop the panic |
Why it matters for interviews
Control flow is the junior-level filter for "knows Go syntax" versus "carries C/Java habits over." The statements themselves are trivial, but the differences from other languages are asked almost every time.
What interviewers usually check:
- Why Go has only one loop and how
forreplaceswhileand the infinite loop. - That a
switchdoes not fall through, and whatfallthroughis then for. - What scope the
if/switchinit statement creates. - What
rangeyields for a slice, amap, a string, and a channel, and why taking the address of the loop variable is dangerous. - How
panic/recoverdiffer from ordinary error handling (errors are values) and whyrecoverworks only indefer.