Go

Spot the bug: why is err nil after the if block?

Question 494MediumGo 1.22 to 1.25
func parse(s string) (int, error) {
    var n int
    var err error
    if s != "" {
        n, err := strconv.Atoi(s) // := declares NEW n and err
        if err != nil {
            log.Println("inner:", err)
        }
        _ = n
    }
    return n, err // always (0, nil)
}

:= inside the if block declares new variables n and err that shadow the outer ones. The outer values are never set, so parse("abc") returns (0, nil) and the error is lost. Fix: use plain assignment, n, err = strconv.Atoi(s).

Related compile-time trap with named results:

func load() (err error) {
    if true {
        _, err := os.Open("x")
        if err != nil {
            return // compile error: result parameter err not in scope at return
        }
    }
    return
}

Also be aware of the redeclaration rule. a, err := f() in the same scope reuses err as long as at least one new variable is on the left. In a nested scope it always creates a new variable. Tools: the shadow analyzer (go vet -vettool=$(which shadow)) and govet's shadow check in golangci-lint.

More on Tricky Output & Code-Review Puzzles

All 38 Tricky Output & Code-Review Puzzles questions