Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why it is possible to redefine err in multiple return statement in Go

Consider the following example illustrating the question (it was just built to explain the question, but I saw similar code in books as well in real projects):

package main

import (
    "strconv"
    "fmt"
    "log"
)

func main() {
    n1, err := strconv.Atoi("1")
    if err != nil {
        log.Panicf("%v", err)
    }

    n2, err := strconv.Atoi("2")
    if err != nil {
        log.Panicf("%v", err)
    }

    // err := fmt.Errorf("new error") <- line 1

    // n1, err := strconv.Atoi("3") <- line 2

    fmt.Printf("n1 = %d, n2 = %d\n", n1, n2)
}

The compiler doesn't complain about redefining err, but if I uncomment <- line 1 or <- line 2, it will complain no new variable on left side of :=.

So, how does it work? Why the compiler happily allows to override err in multi return statement, using :=, but not n1 on <- line 2 example?

Better if you can point into the official reference explaining this behavior.

like image 485
Aliaksandr Kazlou Avatar asked Dec 14 '15 11:12

Aliaksandr Kazlou


1 Answers

It is because you used Short variable declaration :=. Quoting from the spec:

Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block (or the parameter lists if the block is the function body) with the same type, and at least one of the non-blank variables is new. As a consequence, redeclaration can only appear in a multi-variable short declaration. Redeclaration does not introduce a new variable; it just assigns a new value to the original.

This line:

n1, err := strconv.Atoi("1")

Is a multi-variable short declaration, and all variables on the left side are new, and so all will be declared (and return values of strconv.Atoi() assigned).

This line:

n2, err := strconv.Atoi("2")

It is a multi-variable short declaration, and n2 is new. So it declares n2 and only assigns a new value to err, because err is already declared in the same block.

This line:

err := fmt.Errorf("new error") <- line 1

It is not a multi-variable short declaration. It would try to declare err but it is already declared in the same block, therefore it is a compile-time error.

And this line:

n1, err := strconv.Atoi("3") <- line 2

It is a multi-variable short declaration, but all the variables on the left side have been previously declared in the same block, so it is also a compile-time error (it doesn't introduce any new variables on the left side).

Note that if all the variables on the left side have been previously declared, simply changing from Short variable declaration := to Assignment = will make it work (assumed values on the right side are assignable to the variables on the left side).

like image 56
icza Avatar answered Oct 21 '22 07:10

icza