go语言还有一些特殊的控制语句,defer就是其中的一种,defer用于延迟调用指定函数,defer关键字只能出现在函数内部
package main
import "fmt"
func main() {
defer fmt.Println("world")
fmt.Printf("hello")
}
上面的例子会首先打印hello,然后打印world,因为第一句使用了defer关键字,defer语句的会在函数最后执行,被延迟的操作是defer后面的内容。
defer后面的表达式必须是外部函数调用,上面的例子就是针对fmt.println函数的延迟调用
defer有两大特点:
1 :只有当defer语句全部执行,defer所在函数才算真正结束执行
2:当函数中有defer语句时,需要等待所有defer语句执行完毕,才会执行return语句
因为defer的延迟特点,可以吧defer语句用于回收资源,清理收尾等工作,使用defer语句之后,不用纠结回收代码放在哪里,反正都是最后执行
package main
import "fmt"
var i = 0
// func print(){
func print(i int) {
fmt.Println(i)
}
func main() {
for ; i < 5; i++ {
// defer print()
defer print(i)
}
}
如果引入的是一个不带返回值的函数,调用时defer print() ,打印的就都是5。这是因为每个defer都是在函数轮训之后,最后才执行的
package main
import "fmt"
var i = 0
func print() {
// func print(i int) {
fmt.Println(i)
}
func main() {
for ; i < 5; i++ {
defer print()
// defer print(i)
}
}
上面的例子引入了函数参数,虽然还没介绍函数的概念,但是不妨碍理解这里面的defer关键知识。这个之所以是一个反序的数字列表,因为defer其实是一个栈,遵循先入后出,或者理解为先进后出。
当i等于0时,defer语句第一次被压在栈,此时defer后面的函数i返回0;i不断自增,一直等到i等于4时,defer语句第5次入栈,defer后的函数返回4;此时i的自增不在满足for条件,于是跳出循环,在结束之前,go语言会根据defer后进先出的原则逐条打印栈内的数值,于是就倒序输出了。
简单来说就是当一个函数内部有多个defer语句时,最后面的defer语句最先执行。指所有的defer语句中