Skip to content

Commit 18597a7

Browse files
committed
Add defer.md
1 parent 899405f commit 18597a7

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
* [Debugging](posts/debugging.md)
2626
* [Goroutine](posts/goroutine.md)
2727
* [Functional literals](posts/functional-literals.md)
28+
* [defer](posts/defer.md)
2829
* [error vs errors](posts/error-vs-errors.md)
2930
* [Send and receive operations on channel](posts/send-and-receive-operations-on-channel.md)
3031
* [Channel types](posts/channel-types.md)

posts/defer.md

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# defer
2+
----
3+
The `defer` statement is used to postpone a function call executed immediately before the surrounding function returns. The common uses of `defer` include releasing resources (i.e., unlock the mutex, close file handle.), do some tracing(i.e., record the running time of function), etc. E.g., an ordinary accessing global variable exclusively is like this:
4+
5+
var mu sync.Mutex
6+
var m = make(map[string]int)
7+
8+
func lookup(key string) int {
9+
mu.Lock()
10+
v := m[key]
11+
mu.Unlock()
12+
return v
13+
}
14+
An equivalent but concise format using `defer` is as follow:
15+
16+
var mu sync.Mutex
17+
var m = make(map[string]int)
18+
19+
func lookup(key string) int {
20+
mu.Lock()
21+
defer mu.Unlock()
22+
return m[key]
23+
}
24+
You can see this style is more simpler and easier to comprehend.
25+
26+
The `defer` statements are executed in Last-In-First-Out sequence, which means the functions in latter `defer` statements run before their previous buddies. Check the following example:
27+
28+
package main
29+
30+
import "fmt"
31+
32+
func main() {
33+
defer fmt.Println("First")
34+
defer fmt.Println("Last")
35+
}
36+
37+
The running result is here:
38+
39+
Last
40+
First
41+
42+
Although the function in `defer` statement runs very late, the parameters of the function are evaluated when the `defer` statement is executed.
43+
44+
package main
45+
46+
import "fmt"
47+
48+
func main() {
49+
i := 10
50+
defer fmt.Println(i)
51+
i = 100
52+
}
53+
The running result is here:
54+
55+
10
56+
Besides, if the deferred function is a function literal, it can also modify the return value:
57+
58+
package main
59+
60+
import "fmt"
61+
62+
func modify() (result int) {
63+
defer func(){result = 1000}()
64+
return 100
65+
}
66+
67+
func main() {
68+
fmt.Println(modify())
69+
}
70+
71+
The value printed is `1000`, not `100`.
72+
73+
References:
74+
[The Go Programming Language](http://www.gopl.io/);
75+
[Defer, Panic, and Recover](https://blog.golang.org/defer-panic-and-recover).
76+

0 commit comments

Comments
 (0)