How golang's “defer” capture closure's parameter?
up vote
29
down vote
favorite
Here is my code (run):
package main
import "fmt"
func main()
var whatever [5]struct
for i := range whatever
fmt.Println(i)
// part 1
for i := range whatever
defer func() fmt.Println(i) ()
// part 2
for i := range whatever
defer func(n int) fmt.Println(n) (i)
// part 3
Output:
0
1
2
3
4
4
3
2
1
0
4
4
4
4
4
Question: What's the difference between part 2 & part 3? Why part 2 output "44444" instead of "43210"?
add a comment |
up vote
29
down vote
favorite
Here is my code (run):
package main
import "fmt"
func main()
var whatever [5]struct
for i := range whatever
fmt.Println(i)
// part 1
for i := range whatever
defer func() fmt.Println(i) ()
// part 2
for i := range whatever
defer func(n int) fmt.Println(n) (i)
// part 3
Output:
0
1
2
3
4
4
3
2
1
0
4
4
4
4
4
Question: What's the difference between part 2 & part 3? Why part 2 output "44444" instead of "43210"?
add a comment |
up vote
29
down vote
favorite
up vote
29
down vote
favorite
Here is my code (run):
package main
import "fmt"
func main()
var whatever [5]struct
for i := range whatever
fmt.Println(i)
// part 1
for i := range whatever
defer func() fmt.Println(i) ()
// part 2
for i := range whatever
defer func(n int) fmt.Println(n) (i)
// part 3
Output:
0
1
2
3
4
4
3
2
1
0
4
4
4
4
4
Question: What's the difference between part 2 & part 3? Why part 2 output "44444" instead of "43210"?
Here is my code (run):
package main
import "fmt"
func main()
var whatever [5]struct
for i := range whatever
fmt.Println(i)
// part 1
for i := range whatever
defer func() fmt.Println(i) ()
// part 2
for i := range whatever
defer func(n int) fmt.Println(n) (i)
// part 3
Output:
0
1
2
3
4
4
3
2
1
0
4
4
4
4
4
Question: What's the difference between part 2 & part 3? Why part 2 output "44444" instead of "43210"?
edited Jan 14 '16 at 14:40
Paweł Szczur
3,13021928
3,13021928
asked Apr 15 '13 at 8:24
Reck Hou
2,21262444
2,21262444
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
up vote
33
down vote
accepted
The 'part 2' closure captures the variable 'i'. When the code in the closure (later) executes, the variable 'i' has the value which it had in the last iteration of the range statement, ie. '4'. Hence the
4 4 4 4 4
part of the output.
The 'part 3' doesn't capture any outer variables in its closure. As the specs say:
Each time the "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.
So each of the defered function calls has a different value of the 'n' parameter. It is the value of the 'i' variable in the moment the defer statement was executed. Hence the
4 3 2 1 0
part of the output because:
... deferred calls are executed in LIFO order immediately before the surrounding function returns ...
The key point to note is that the 'f()' in 'defer f()' is not executed when the defer statement executes
but
the expression 'e' in 'defer f(e)' is evaluated when the defer statement executes.
add a comment |
up vote
0
down vote
I would like to address another example in order to improve the understanding of defer mechanish, run this snippet as it is first, then switch order of the statements marked as (A) and (B), and see the result to yourself.
package main
import (
"fmt"
)
type Component struct
val int
func (c Component) method()
fmt.Println(c.val)
func main()
c := Component
defer c.method() // statement (A)
c.val = 2 // statement (B)
I keep wonderng what are the correct keywords or concepts to apply here. It looks like that the expression c.method is evaluated, thus returning a function binded to the actual state of the component "c" (like taking an snapshot of the component's internal state).
I guess the answer involves not only defer mechanish also how funtions with value or pointer receiver works. Do note that it also happens that if you change the func named method to be a pointer receiver the defer prints c.val as 2, not as 0.
maybe this is a complex example of something like this play.golang.org/p/yNma_82QIJ9
– Victor
Nov 12 at 18:11
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
33
down vote
accepted
The 'part 2' closure captures the variable 'i'. When the code in the closure (later) executes, the variable 'i' has the value which it had in the last iteration of the range statement, ie. '4'. Hence the
4 4 4 4 4
part of the output.
The 'part 3' doesn't capture any outer variables in its closure. As the specs say:
Each time the "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.
So each of the defered function calls has a different value of the 'n' parameter. It is the value of the 'i' variable in the moment the defer statement was executed. Hence the
4 3 2 1 0
part of the output because:
... deferred calls are executed in LIFO order immediately before the surrounding function returns ...
The key point to note is that the 'f()' in 'defer f()' is not executed when the defer statement executes
but
the expression 'e' in 'defer f(e)' is evaluated when the defer statement executes.
add a comment |
up vote
33
down vote
accepted
The 'part 2' closure captures the variable 'i'. When the code in the closure (later) executes, the variable 'i' has the value which it had in the last iteration of the range statement, ie. '4'. Hence the
4 4 4 4 4
part of the output.
The 'part 3' doesn't capture any outer variables in its closure. As the specs say:
Each time the "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.
So each of the defered function calls has a different value of the 'n' parameter. It is the value of the 'i' variable in the moment the defer statement was executed. Hence the
4 3 2 1 0
part of the output because:
... deferred calls are executed in LIFO order immediately before the surrounding function returns ...
The key point to note is that the 'f()' in 'defer f()' is not executed when the defer statement executes
but
the expression 'e' in 'defer f(e)' is evaluated when the defer statement executes.
add a comment |
up vote
33
down vote
accepted
up vote
33
down vote
accepted
The 'part 2' closure captures the variable 'i'. When the code in the closure (later) executes, the variable 'i' has the value which it had in the last iteration of the range statement, ie. '4'. Hence the
4 4 4 4 4
part of the output.
The 'part 3' doesn't capture any outer variables in its closure. As the specs say:
Each time the "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.
So each of the defered function calls has a different value of the 'n' parameter. It is the value of the 'i' variable in the moment the defer statement was executed. Hence the
4 3 2 1 0
part of the output because:
... deferred calls are executed in LIFO order immediately before the surrounding function returns ...
The key point to note is that the 'f()' in 'defer f()' is not executed when the defer statement executes
but
the expression 'e' in 'defer f(e)' is evaluated when the defer statement executes.
The 'part 2' closure captures the variable 'i'. When the code in the closure (later) executes, the variable 'i' has the value which it had in the last iteration of the range statement, ie. '4'. Hence the
4 4 4 4 4
part of the output.
The 'part 3' doesn't capture any outer variables in its closure. As the specs say:
Each time the "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.
So each of the defered function calls has a different value of the 'n' parameter. It is the value of the 'i' variable in the moment the defer statement was executed. Hence the
4 3 2 1 0
part of the output because:
... deferred calls are executed in LIFO order immediately before the surrounding function returns ...
The key point to note is that the 'f()' in 'defer f()' is not executed when the defer statement executes
but
the expression 'e' in 'defer f(e)' is evaluated when the defer statement executes.
edited Apr 15 '13 at 9:43
answered Apr 15 '13 at 8:32
zzzz
51.8k12126112
51.8k12126112
add a comment |
add a comment |
up vote
0
down vote
I would like to address another example in order to improve the understanding of defer mechanish, run this snippet as it is first, then switch order of the statements marked as (A) and (B), and see the result to yourself.
package main
import (
"fmt"
)
type Component struct
val int
func (c Component) method()
fmt.Println(c.val)
func main()
c := Component
defer c.method() // statement (A)
c.val = 2 // statement (B)
I keep wonderng what are the correct keywords or concepts to apply here. It looks like that the expression c.method is evaluated, thus returning a function binded to the actual state of the component "c" (like taking an snapshot of the component's internal state).
I guess the answer involves not only defer mechanish also how funtions with value or pointer receiver works. Do note that it also happens that if you change the func named method to be a pointer receiver the defer prints c.val as 2, not as 0.
maybe this is a complex example of something like this play.golang.org/p/yNma_82QIJ9
– Victor
Nov 12 at 18:11
add a comment |
up vote
0
down vote
I would like to address another example in order to improve the understanding of defer mechanish, run this snippet as it is first, then switch order of the statements marked as (A) and (B), and see the result to yourself.
package main
import (
"fmt"
)
type Component struct
val int
func (c Component) method()
fmt.Println(c.val)
func main()
c := Component
defer c.method() // statement (A)
c.val = 2 // statement (B)
I keep wonderng what are the correct keywords or concepts to apply here. It looks like that the expression c.method is evaluated, thus returning a function binded to the actual state of the component "c" (like taking an snapshot of the component's internal state).
I guess the answer involves not only defer mechanish also how funtions with value or pointer receiver works. Do note that it also happens that if you change the func named method to be a pointer receiver the defer prints c.val as 2, not as 0.
maybe this is a complex example of something like this play.golang.org/p/yNma_82QIJ9
– Victor
Nov 12 at 18:11
add a comment |
up vote
0
down vote
up vote
0
down vote
I would like to address another example in order to improve the understanding of defer mechanish, run this snippet as it is first, then switch order of the statements marked as (A) and (B), and see the result to yourself.
package main
import (
"fmt"
)
type Component struct
val int
func (c Component) method()
fmt.Println(c.val)
func main()
c := Component
defer c.method() // statement (A)
c.val = 2 // statement (B)
I keep wonderng what are the correct keywords or concepts to apply here. It looks like that the expression c.method is evaluated, thus returning a function binded to the actual state of the component "c" (like taking an snapshot of the component's internal state).
I guess the answer involves not only defer mechanish also how funtions with value or pointer receiver works. Do note that it also happens that if you change the func named method to be a pointer receiver the defer prints c.val as 2, not as 0.
I would like to address another example in order to improve the understanding of defer mechanish, run this snippet as it is first, then switch order of the statements marked as (A) and (B), and see the result to yourself.
package main
import (
"fmt"
)
type Component struct
val int
func (c Component) method()
fmt.Println(c.val)
func main()
c := Component
defer c.method() // statement (A)
c.val = 2 // statement (B)
I keep wonderng what are the correct keywords or concepts to apply here. It looks like that the expression c.method is evaluated, thus returning a function binded to the actual state of the component "c" (like taking an snapshot of the component's internal state).
I guess the answer involves not only defer mechanish also how funtions with value or pointer receiver works. Do note that it also happens that if you change the func named method to be a pointer receiver the defer prints c.val as 2, not as 0.
edited Nov 12 at 15:48
answered Nov 9 at 19:08
Victor
2,38222143
2,38222143
maybe this is a complex example of something like this play.golang.org/p/yNma_82QIJ9
– Victor
Nov 12 at 18:11
add a comment |
maybe this is a complex example of something like this play.golang.org/p/yNma_82QIJ9
– Victor
Nov 12 at 18:11
maybe this is a complex example of something like this play.golang.org/p/yNma_82QIJ9
– Victor
Nov 12 at 18:11
maybe this is a complex example of something like this play.golang.org/p/yNma_82QIJ9
– Victor
Nov 12 at 18:11
add a comment |
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f16010694%2fhow-golangs-defer-capture-closures-parameter%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown