Is golang defer statement execute before or after return statement?

golang defer return
golang defer anonymous function
golang panic vs fatal
golang panic format string
golang when to use panic
golang defer timing
golang exit defer
golang defer blog

I have a question about golang defer: Is golang defer statement execute before or after return statement?

I have read Defer_statements. But I do not got the answer.

I made a simple test:

func test1() (x int) {
    defer fmt.Printf("in defer: x = %d\n", x)

    x = 7
    return 9
}

func test2() (x int) {
    defer func() {
        fmt.Printf("in defer: x = %d\n", x)
    }()

    x = 7
    return 9
}

func test3() (x int) {
    x = 7
    defer fmt.Printf("in defer: x = %d\n", x)
    return 9
}

func main() {
    fmt.Println("test1")
    fmt.Printf("in main: x = %d\n", test1())
    fmt.Println("test2")
    fmt.Printf("in main: x = %d\n", test2())
    fmt.Println("test3")
    fmt.Printf("in main: x = %d\n", test3())
}

In test1(), using Printfto print x after defer. In test2(), using a anonymous function to print x after defer. In test3(), using Printfto print x after defer, but defer after x = 7.

But the result is:

test1
in defer: x = 0
in main: x = 9
test2
in defer: x = 9
in main: x = 9
test3
in defer: x = 7
in main: x = 9

So, is any one can explain: 1. why got this result? why test1 prints 0, test2 print9, test3 prints 7. 2. is defer statement excutes after return or before return?

Thanks a lot.

Thanks @dev.bmax @Tranvu Xuannhat @rb16. With your help, I found the key explanation from Defer_statements.

Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked.

We can break up defer ... into three parts.

  1. invoke defer, evaluating the value of function parameter.
  2. execute defer, pushing a function in to stack.
  3. execute functions in stack after return or panic.

I made a new test4 to explain.

func test4() (x int) {
    defer func(n int) {
        fmt.Printf("in defer x as parameter: x = %d\n", n)
        fmt.Printf("in defer x after return: x = %d\n", x)
    }(x)

    x = 7
    return 9
}

In test4,

  1. invoke defer, evaluating the value of n, n = x = 0, so x as parameter is 0.
  2. execute defer, pushing func(n int)(0) onto stack.
  3. execute func(n int)(0) after return 9, n in fmt.Printf("in defer x as parameter: x = %d\n", n) has been evaluated, x in fmt.Printf("in defer x after return: x = %d\n", x) will be evaluated now, x is 9。

So, got the result:

test4
in defer x as parameter: x = 0
in defer x after return: x = 9
in main: x = 9

Defer, call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns. Defer statement is used to execute a function call just before the surrounding function where the defer statement is present returns. The definition might seem complex but it's pretty simple to understand by means of an example.

In the first test, the value of the parameter x is evaluated when the line containing the defer runs. And it happens in line 1 when x is still 0.

Note, that even though fmt.Printf will be called later, it's parameters are evaluated ahead of time.

In the third test, the value of the parameter x is set to 7 before the defer statement runs. Again, this happens before the actual invocation of fmt.Printf.

The second test is a little different. Variable x is within the scope of the anonymous function. It's value is evaluated when the function runs, which happens when the test function returns. By that time x is 9.

Defer Keyword in Golang, function or method call arguments evaluate instantly, but they execute until the nearby functions returns. defer statement is a convenient way to execute a piece of code before a function returns, as explained in Golang specification: Instead, deferred functions are invoked immediately before the surrounding function returns, in the reverse order they were deferred. Here is an example of the LIFO (last-in-first-out) implementation: func main()

Defer, Panic, and Recover, executed normally, and then F returns to its caller. CODE EXAMPLE A deferred function is executed when the surrounding function returns, either on exit or on panic. Deferred functions are commonly used for clean-up actions, such as closing a file or unlocking a mutex. CODE EXAMPLE A deferred function is executed when the surrounding function returns, either on exit or on panic.

It's not before or after, it's all about if the defer statement is present in the stack or not. if it is (if the control reaches to the defer statement it saves stores statement into the stack), then after it will execute after the return statement.

for example -

func testing() err {
    x, err := doSomething();
    if err != nil {
       return;
    }
    defer fmt.Println("hello")
    return nil
}

So if err != nil this defer will never execute, because program returned before the control reaches to the defer statement.

Now come to your Question (all will reach to the defer statement) 1. case, the statement stored in the stack is defer fmt.Printf("in defer: x = %d\n", x) (with zero value of x)

  1. case - the statement stored in the stack is A function

defer func() { fmt.Printf("in defer: x = %d\n", x) }()

Which is dependent on x (Note in the stack the defer statement is a function, and the value of a function will be assigned at the time of function execution)

  1. Case - defer fmt.Printf("in defer: x = %d\n", x) with value 7

Simple Guide to Panic Handling and Recovery in Golang, Close before the second return statement, but if the function were more Deferred function calls are executed in Last In First Out order after the  Defer is used to ensure that a function call is performed later in a program’s execution, usually for purposes of cleanup. defer is often used where e.g. ensure and finally would be used in other languages. #N#import ( "fmt" "os" ) Suppose we wanted to create a file, write to it, and then close when we’re done. Here’s how we could do that

A defer statement defers the execution of a function until the surrounding function returns. The deferred call's arguments are evaluated immediately, but the  Defer, Panic, and Recover. Andrew Gerrand 4 August 2010 Go has the usual mechanisms for control flow: if, for, switch, goto. It also has the go statement to run code in a separate goroutine. Here I'd like to discuss some of the less common ones: defer, panic, and recover. A defer statement pushes a function call onto a list. The list of saved

package main import "fmt" func main() { // defer statement is executed, and places // fmt.Println("Bye") on a list to be executed prior to the function returning Close​() statement is also going to run after the return statement. defer statement is a convenient way to execute a piece of code before a function returns, as explained in Golang specification: Go runtime implements the LIFO with a linked list. Indeed, a defer…

In Go language, defer statements delay the execution of the function or method or an anonymous method until the nearby functions returns. Or in other words,  If with a short statement. Like for, the if statement can start with a short statement to execute before the condition. Variables declared by the statement are only in scope until the end of the if. (Try using v in the last return statement.) <