Search code examples
goscopereturndeferred-execution

Why isn't the return value returned when this deferred statement (without a return) runs?


I am reading through the go specification and don't fully understand the behavior of an example for defer.

// f returns 1
func f() (result int) {
    defer func() {
        result++
    }()
    return 0
}

The function has a named return, which an anonymous deferred function increments. The function ends with "return 0". This value is not returned, but the incremented variable instead.

In trying to understand this behavior, I've run into more questions. If I assign a value to the return variable, that seems to have no effect on the return value.

//b returns 1
func b() (result int) {
    result = 10
    defer func() {
        result++
    }()
    return 0
}

However, if the last line is changed to:

return result

Things behave as I would expect.

https://play.golang.org/p/732GZ-cHPqU

Can someone help me better understand why these values get returned and the scope of these functions.


Solution

  • The specification says this about deferred functions:

    if the deferred function is a function literal and the surrounding function has named result parameters that are in scope within the literal, the deferred function may access and modify the result parameters before they are returned.

    and and this about return statements:

    A "return" statement that specifies results sets the result parameters before any deferred functions are executed.

    Example 1:

    func f() (result int) {
        defer func() {
            result++
        }()
        return 0
    }
    

    The result variable is initialized to zero; the return statement sets result to zero; the deferred function increments result to 1; the function returns 1.

    Example 2:

    func b() (result int) {
        result = 10
        defer func() {
            result++
        }()
        return 0
    }
    

    The result variable is set to 10 in the first statement of the function; the return statement sets result to zero; the deferred function increments result to 1; the function returns 1.

    Example 3:

    func c() (result int) {
        result = 10
        defer func() {
            result++
        }()
        return result
    }
    

    The result variable is set to 10 in the first statement of the function; the return statement sets result to 10; the deferred function increments result to 11, the function returns 11.