# 1.1 延迟是什么?
即延迟(defer)语句,延迟语句被用于执行一个函数调用,在这个函数之前,延迟语句返回。
# 1.2 延迟函数
你可以在函数中添加多个defer语句。当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回。特别是当你在进行一些打开资源的操作时,遇到错误需要提前返回,在返回前你需要关闭相应的资源,不然很容易造成资源泄露等问题
- 如果有很多调用defer,那么defer是采用
后进先出
模式 - 在离开所在的方法时,执行(报错的时候也会执行)
func ReadWrite() bool {
file.Open("file")
defer file.Close()
if failureX {
return false
}
if failureY {
return false
}
return true
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
最后才执行file.Close()
示例代码:
package main
import "fmt"
func main() {
a := 1
b := 2
defer fmt.Println(b)
fmt.Println(a)
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
运行结果:
1
2
1
2
2
示例代码:
package main
import (
"fmt"
)
func finished() {
fmt.Println("Finished finding largest")
}
func largest(nums []int) {
defer finished()
fmt.Println("Started finding largest")
max := nums[0]
for _, v := range nums {
if v > max {
max = v
}
}
fmt.Println("Largest number in", nums, "is", max)
}
func main() {
nums := []int{78, 109, 2, 563, 300}
largest(nums)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
运行结果:
Started finding largest
Largest number in [78 109 2 563 300] is 563
Finished finding largest
1
2
3
2
3
# 1.3 延迟方法
延迟并不仅仅局限于函数。延迟一个方法调用也是完全合法的。让我们编写一个小程序来测试这个。
示例代码:
package main
import (
"fmt"
)
type person struct {
firstName string
lastName string
}
func (p person) fullName() {
fmt.Printf("%s %s",p.firstName,p.lastName)
}
func main() {
p := person {
firstName: "John",
lastName: "Smith",
}
defer p.fullName()
fmt.Printf("Welcome ")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
运行结果:
Welcome John Smith
1
# 1.4 延迟参数
延迟函数的参数在执行延迟语句时被执行,而不是在执行实际的函数调用时执行。
让我们通过一个例子来理解这个问题。
示例代码:
package main
import (
"fmt"
)
func printA(a int) {
fmt.Println("value of a in deferred function", a)
}
func main() {
a := 5
defer printA(a)
a = 10
fmt.Println("value of a before deferred function call", a)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
运行结果:
value of a before deferred function call 10
value of a in deferred function 5
1
2
2
# 1.5 堆栈的推迟
当一个函数有多个延迟调用时,它们被添加到一个堆栈中,并在Last In First Out(LIFO)后进先出的顺序中执行。
我们将编写一个小程序,它使用一堆defers打印一个字符串。示例代码:
package main
import (
"fmt"
)
func main() {
name := "Naveen"
fmt.Printf("Orignal String: %s\n", string(name))
fmt.Printf("Reversed String: ")
for _, v := range []rune(name) {
defer fmt.Printf("%c", v)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
运行结果:
Orignal String: Naveen
Reversed String: neevaN
1
2
2
# 1.6 defer注意点
defer函数:
当外围函数中的语句正常执行完毕时,只有其中所有的延迟函数都执行完毕,外围函数才会真正的结束执行。
当执行外围函数中的return语句时,只有其中所有的延迟函数都执行完毕后,外围函数才会真正返回。
当外围函数中的代码引发运行恐慌时,只有其中所有的延迟函数都执行完毕后,该运行时恐慌才会真正被扩展至调用函数。
1
2
3
4
2
3
4