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



