golang基础--细说defer

failymao · · 59 次点击 · · 开始浏览    

defer 匿名函数特性

  • 执行方式类似其它语言中的析构函数,在函数体执行结束后按照调用顺序的相反顺序逐个执行

    //执行顺序相反
    package main
    import "fmt"
    
    func main() {
        fmt.Println("a")
        defer fmt.Println("b")
        defer fmt.Println("c")
    }
    /*输出
    a
    c
    b
    */
  • 即使函数发生严重的错误也会执行,类似于try...except
  • 常用于 资源清理,文件关闭,解锁以及记录时间等操作

  • 支持匿名函数的调用
  • 通过于匿名函数配合可在return之后修改函数计算的结果
    -如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer时即已经获得了拷贝,否则 则时引用某个变量的地址

    //支持匿名函数
    package main
    import "fmt"
    
    func main() {
        for i := 0; i < 3; i++ {
            defer func() { //函数体内的变量传递到defer匿名函数
                fmt.Println(i) //此时引用的时变量i的地址
            }()
        }
    }
    
    /*输出
    3
    3
    3
    */
  • Go没有异常机制,但有panic/recover模式来处理错误
  • Panic可以在任何地方引发

    panic错误机制

    //panic 错误机制,遇到panic语句后,后面不会再执行
    package main
    import "fmt"
    func main() {
        A()
        B()
        C()
    }
    
    func A() {
        fmt.Println("func a")
    }
    
    func B() {
        panic("Panic B")
    }
    func C() {
        fmt.Println("func")
    }
    
    /*输出
    A()-->  func a
    B()---> panic: Panic B
    ---------------
        goroutine 1 [running]:
        main.B()
    C()     C:/Users/faily/Desktop/workspace/src/defer1.go:17 +0x40
        main.main()
            C:/Users/faily/Desktop/workspace/src/defer1.go:8 +0x2c
        exit status 2
        exit status 1
    */
  • defer,配合recover及匿名函数处理程序出现的严重错误(panic语句),调过程序错误,继续执行,类似于python语言中 try...except,finally语句.

    //defer,recover机制,处理panic引发的机制
    package main
    import "fmt"
    
    func main() {
        A()
        B()
        C()
    }
    
    func A() {
        fmt.Println("func a")
    }
    func B() {
        defer func() {                          //defer函数放在panic之前
            if err := recover(); err != nil {   //注册recover函数(判断是否触发panic错误),并判断
                fmt.Println("Recover in B")     //如果程序出现panic,并且err不为nil(真实存在)
            } 
        }()                                     //记住,defer的匿名函数大括号后要加上()                                
        panic("Panic B")                        //跳过程序错误,继续后面的执行。
    
    }
    func C() {
        fmt.Println("func C")
    
    }
    
    /*输出
    A()-->  func a
    B()-->  Recover in B
    C()-->  func C
    */ 

    ~~留一个问题,感兴趣的小伙伴欢迎作答

    运行以下代码,并分析输出结果

    package main
    import "fmt"
    
    func main() {
    var fs = [4]func(){} //定义一个变量fs,类型为一个数组,数组元素的类型是 func
    
    for i := 0; i < 4; i++ {
        defer fmt.Println("defer i=", i)
        defer func() { fmt.Println("defer closure i=", i) }()
        fs[i] = func() { fmt.Println("closure i=", i) }
    }
    for _, f := range fs {
        f()
    }
    }

本文来自:博客园

感谢作者:failymao

查看原文:golang基础--细说defer

59 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传