defer
defer意思是推迟、延迟。语法很简单,就在正常的语句前加上defer就可以了。
在某函数中使用defer语句,会使得defer后跟的语句进行延迟处理,当该函数即将返回时,或发生panic时,defer后语句开始执行。注意os.Exit不是这两种情况,不会执行defer。
同一个函数可以有多个defer语句,依次加入调用栈中(LIFO),函数返回或panic时,从栈顶依次执行defer后语句。执行的先后顺序和注册的顺序正好相反,也就是后注册的先执行。
defer后的语句必须是一个函数或方法的调用
//执行的先后顺序和注册的顺序正好相反,也就是后注册的先执行。
package mainimport "fmt"func main() {fmt.Println("start")defer fmt.Println(1)defer fmt.Println(2)defer fmt.Println(3)fmt.Println("end")
}
start
end
3
2
1
package mainimport "fmt"func main() {count := 1fmt.Println("start")defer fmt.Println(count) //1count++defer fmt.Println(count) //2count++defer fmt.Println(count) //3fmt.Println("end")
}
start
end
3
2
1
//为什么?因为defer注册时就,就把其后语句的延迟执行的函数的实际参数准备好了,也就是注册时计算。
package mainimport "fmt"func main() {count := 1fmt.Println("start")defer func() { fmt.Println(count) }() // fmt.Println(count) 因为注册时要确定实际参数,而这是个匿名无参函数,没法准备参数。延迟执行时,打印是才要用count,其外部作用域有一个count,目前是3。count++defer fmt.Println(count)count++defer fmt.Println(count) fmt.Println("end")
}
start
end
3
2
3
package mainimport "fmt"func main() {count := 1fmt.Println("start")defer func(count int) { fmt.Println(count) }(count) //确定了实际参数,直接传参进去为1fmt.Println(count)count++defer fmt.Println(count)count++defer fmt.Println(count)fmt.Println("end")
}
start
1
end
3
2
1