延迟语句--defer

一、初识defer

func main(){
    defer fmt.println("world")
    fmt.println("hello")
}

==>hello
      world
=>defer语句会在函数最后执行,被延迟操作的是defer后面的内容

二、特点

defer后面的表达式必须是外部函数的调用.上面的例子是针对fmt.println函数的延迟调用

1)只有当defer语句全部执行,defer所在的函数才能算真正结束执行

2)当函数中有defer语句时,需要等待所有defer语句执行完毕,才会执行return语句

=》defer常用于回收资源,清理收尾

func print(){
    fmt.println("hello")
}
func main(){
    for ;i<5;i++{
        defer print()
    }
}
==>5,5,5,5,5

func print(i int){
    fmt.println(i)
}
func main(){
    for ;i<5;i++{
        defer print(i)
    }
}
==>4,3,2,1,0(相当于先储存(0,1,2,3,4)),在输出(4,3,2,1,0)【这也是所谓的后进先出】

一道考察defer与命名返回值的题目

返回4,1,3
解释:
defer和return以及返回值的关系是defer最先执行一些收尾工作,然后return执行,return负责将结果写入返回值,最后函数携带当前返回值退出,所以:

func a()(i int){
    defer funcA(){
    }
    defer funcB(){
    }
}
先运行funcB再运行funcA

回到上面的代码,DeferFunc2 函数没有可命名结果形参,t只是个普通局部变量,defer无法对返回值做修改;DeferFunc1 和DeferFunc3的运行逻辑是:

DeferFunc1:
t:= 0
t = 1
t +=3 -> t = 4

DeferFunc3:
t:=0
t = 2
t += 1 -> t = 3

对于返回值是否命名关乎到main函数内调用其他含有defer的函数时,是否可以获取真实的返回值,即没命名返回0,有命名返回最后一次defer的输出。

三.代码跟踪

func main(){
    b()
}
func a(){
    defer un(trace("a")) //初始化defer函数的参数,所以输出trace()的结果
    fmt.Println("a的逻辑代码")
}
func a(){   
   defer un(trace("a"))   
   fmt.Println("b的逻辑代码")
   a()
}
func trace(s string)string{
    fmt.Println("开始执行",s)
    return s
}
func un(s string){
    fmt.Println("结束执行",s)
}
=>开始执行b
    b的逻辑代码
    开始执行a
    a的逻辑代码
    结束执行a
    结束执行b

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容