Go

What does this print? (Shadowed err)

Question 318MediumGo 1.22 to 1.25
func parse(s string) error {
	var err error
	if s != "" {
		n, err := strconv.Atoi(s) // := declares a NEW err in this block
		if err == nil {
			fmt.Println("parsed", n)
		}
	}
	return err
}

func main() {
	fmt.Println(parse("abc")) // <nil>
}

It prints <nil>. Inside the if block, := declares new variables n and err that shadow the outer err. The Atoi failure goes to the inner variable and is lost when the block ends, so the function reports success. The shadow analyzer (install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow, then run go vet -vettool=$(which shadow)) and golangci-lint's govet shadow check flag this.

A related gotcha is a bare return with named results. If a named result is shadowed in the scope of the return, it's a compile error: err is shadowed during return.

func f() (err error) {
	if _, err := os.Open("x"); err != nil {
		return // compile error: err is shadowed during return
	}
	return
}

Fix: declare n first and use = (var n int; n, err = strconv.Atoi(s)), or return from inside the block.

More on Error Handling & panics

All 37 Error Handling & panics questions