Search code examples
goerror-handlingdefer-keyword

When defer func evaluates its parameters


I am learning how defer behaves in golang, and want to use it to handle error when the function returns.

Code is as below:

package main

import "fmt"
import "errors"

func main() {
    a()
}

func a() {
    var err error   
    defer func(){
        if err != nil {
            fmt.Printf("1st defer: %s\n", err)
        } else {
            fmt.Println("1st defer: defer not error")
        }
    }()
    defer func(err error){
        if err != nil {
            fmt.Printf("2nd defer: %s\n", err)
        } else {
            fmt.Println("2nd defer: defer not error")
        }
    }(err)

    err = errors.New("new error")
    if err != nil {
        return
    }
}

The output:

2nd defer: defer not error
1st defer: new error

Doc says parameters are evaluated when the defer call is evaluated, which seems it should be consistent. Why 2 defer has different value for variable err and thusly different output? I know it is related to 2nd function has err as input parameter, but don't know why.


Solution

  • Ok I just figured out. If you pass any parameters to the defer func (like the 2nd defer function above), those parameters are evaluated when the defer function is deferred, not when they are executed. That means in my example err is still nil and has not been assigned to a new error yet.

    on the other hand, in 1st defer above, err is not a parameter, but a variable in function a, and when 1st defer is executed, it has already been assigned to a new error.