-3

golang's documentation says this:

A deferred function's arguments are evaluated when the defer statement is evaluated.

This confuses me.

Question: Does "evaluated" mean that the value is already known? I just don't understand why two examples print different. This confuse me.

I have two examples below:

 //It prints 0.
 func deferA() {
     i := 0
     defer fmt.Println(i)
     i++
     return
 }

 //It prints 1.
 func deferB() {
      i := 0
      defer func() {
          fmt.Println(i)
      }()
      i++
      return
 }
Dan Super
  • 83
  • 1
  • 4
  • A defer statement defers the execution of a function until the surrounding function returns. The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns. – Neha Dec 29 '17 at 10:25

2 Answers2

3

defer take a function, so fmt.Println(i) is a function and its argument i is evaluated as 0 when the defer statement is evaluated.

defer func() { fmt.Println(i) }, the func() { fmt.Println(i) } take no argument and its a closure, so i is not evaluated but close over by the closure.

You can more information about closure at https://gobyexample.com/closures

Morty Choi
  • 2,466
  • 1
  • 18
  • 26
1

Function arguments are evaluated, but not function itself.

In first case argument I is evaluated and value 0 is prepared to be passed to function. That’s why deferred function prints 0.

In second case there’re no arguments to evaluate. But function encloses value from outer function. So it has direct access to its actual value.

You may achieve the same result without closure. Pass an address of variable i. Logics is the same : address is computed and passed to the function. Having this address function has access to actual variable value. Try it to check how it works.

Eugene Lisitsky
  • 12,113
  • 5
  • 38
  • 59