| 
                            
                                  go的defer和return的执行顺序go的defer和return是golang中的两个关键字,return用于返回函数的返回值,也可以参与一定的流程控制,比如下面代码,return短路了后面的输出 
	
		
			| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package main   import "fmt"   // defer 和 return的详解 func main() {     foo(2)     foo(1) } func foo(i int) {     fmt.Println(i)     if i == 1 {         return     }     fmt.Println(i + 1) } |  结果: 
23
 1
 第一次输出完整的输出了i和i+1,第二次输出被短路,只输出了1 defer是golang中的延迟调用,经常用于文件流的关闭,锁的解锁操作,defer后面的操作会在当前函数或者goroutine结束之后进行调用 
	
		
			| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package main   import "fmt"   // defer 和 return的详解 func main() {     foo() } func foo() {     defer fmt.Println("println defer")     fmt.Println("println foo") }   输出: println foo println defer |  defer自身有一些特性,比如defer和defer之间的执行顺序是先进后出,先defer的最后执行,分析下面代码: 
	
		
			| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package main   import "fmt"   // defer 和 return的详解 func main() {     foo() } func foo() {     defer fmt.Println("floor 3")     defer fmt.Println("floor 2")     fmt.Println("floor 1") }   输出: floor 1 floor 2 floor 3 |  根据这一特性,如果我们defer调用的代码中存在panic 的可能性,为了保证系统的运行,我们应该在前面recover而不是后面 
	
		
			| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | ackage main   import "fmt"   // defer 和 return的详解 func main() {     foo() } func foo() {     defer func() {         panic("panic test")     }()     defer func() {         if err := recover(); err != nil {             fmt.Println("catch panic:", err)         }     }() }   输出: panic: panic test |  
	
		
			| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package main   import "fmt"   // defer 和 return的详解 func main() {     foo() } func foo() {     defer func() {         if err := recover(); err != nil {             fmt.Println("catch panic:", err)         }     }()     defer func() {         panic("panic test")     }() } 输出: catch panic: panic test |  defer和return的相互影响defer和return的相互影响,主要是在返回值上表现,考虑下面代码,输出应该是什么: 
	
		
			| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import "fmt"   // defer 和 return的详解 func main() {     fmt.Println(foo1())     fmt.Println(foo2())     fmt.Println(foo3()) } func foo1() int {     i := 1     defer func() { i++ }()     return i } func foo2() (i int) {     i = 1     defer func() { i++ }()     return i } func foo3() (i int) {     defer func() { i++ }()     return 1 } |  输出: 
12
 2
 导致上面情况的原因是 在 foo1 函数中,defer 语句中的闭包会在函数返回后执行,但是此时返回值已经确定为 1 ,所以最终返回 1 。 在 foo2 函数中,使用了命名返回值 i 。defer 语句中的闭包修改的是这个命名返回值,所以返回 2 。 在 foo3 函数中,同样使用了命名返回值 i ,defer 语句中的闭包修改了这个命名返回值,并且函数直接返回 1 ,但 defer 中的修改使得最终返回 2 。 而return的另一个特性,也会影响return和defer中代码的执行顺序 
	
		
			| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package main   import "fmt"   // defer 和 return的详解 func main() {     fmt.Println(foo1())   } func foo1() int {     defer func() { fmt.Println("This is defer") }()     return func() int {         fmt.Println("This is return")         return 1     }() }   输出: This is return This is defer 1 |  导致上面输出的原因是,return是非原子性的,defer会在return返回值之前执行,但return中的语句,会被全部执行,直到return锚定了某个值或者命名返回值,然后执行defer语句,最后返回return锚定的这个值 
 |