Scope and blocks
Go is lexically scoped; whether a name exists, shadows another, or is visible at all depends on its block.
Canonical guidance
- every declaration has a lexical scope
- inner blocks can shadow outer names
- labels have their own scope rules separate from ordinary identifiers
Use when
- explaining undefined names
- reviewing
if,for, orswitchinitializers - reasoning about shadowing and lifetime of locals
Avoid
- assuming scope follows indentation rather than blocks
- reusing names across nested control-flow blocks casually
- widening variable scope when a smaller block would be clearer
Preferred pattern
if err := validate(req); err != nil {
return err
}
Anti-pattern
- declaring a variable in an
ifinitializer and expecting it to exist after theifends
Explanation: This is tempting because the code reads linearly, but initializer scope is limited to the statement and its branches.
Why
- Go compile errors about names usually come from scope rules, not from runtime behavior