golang基础--细说defer

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()
    }
    }

原文地址:https://www.cnblogs.com/failymao/p/9297334.html

时间: 2024-10-08 13:10:59

golang基础--细说defer的相关文章

【Golang基础】defer执行顺序

defer 执行顺序类似栈的先入后出原则(FILO) 一个defer引发的小坑:打开文件,读取内容,删除文件 // 原始问题代码 func testFun(){ // 打开文件 file, err := os.Open(path) defer file.Close() // do something // 删除文件 defer func() { removeErr := os.Remove(path) if removeErr != nil { fmt.Println(removeErr) }

golang学习之defer

golang中的defer通常用于执行一些资源释放性操作,比如open/close.connect/disconnect.lock/unlock等,对defer理解主要记住以下三点: 1.defer 调用的函数参数的值 defer 被定义时就确定 举个例子,看如下代码: i := 1 defer fmt.Println("Deferred print:", i) i++ fmt.Println("Normal print:", i) 正确输出如下: Normal p

Golang基础入门

Go语言很容易上手 第一步,在你的计算机上安装Go语言环境 首先下载对应操作系统的安装包或者源文件 Windows和Mac OSX 都有安装包,可以选择直接双击安装,很简单 Ubuntu系统可以使用 apt-get 安装 sudo apt-get install golang 当然,你也可以选择使用源码包安装 获取源码: $ hg clone -u release https://code.google.com/p/go 进入到源码目录,运行安装脚本 $ cd go/src $ ./all.ba

Golang基础学习总结

1.不支持继承 重载 ,比如C++Java的接口,接口的修改会影响整个实现改接口的类行为的修改,Go 设计者认为这一特点或许根本没用. 2.必任何函数定义必须花括号跟在函数声明后面而不能换行 如 func  funca(a int){},在Go语言中 函数也是一种类型 可以被推导  使用支持匿名函数 和闭包. 函数的返回值支持多重返回类似Python , 如果不赋值  整数类型默认 0     浮点数类型默认0.0   error类型 默认是nil 3.不用的包一定不要引入,这是Go的原则,就如

【GoLang】panic defer recover 深入理解

先等我想清楚golang错误处理 为什么要这么设计的时候 再来更新... Golang这么时尚的语言是没有类似try..catch 这种异常处理机制,而是使用 panic 和 recover处理异常. 其实相当于python的raise. golang的异常处理组合 panic,defer,recover,跟java中的try catch finially是类似的. 但是从语言的用户体验来说,不怎么好. 但考虑到golang的场景基本是系统高性能层面的,这种精准错误处理应该减少那种后遗症bug.

Golang基础

Go语言基础 关键字 break, default, func, interface, select case, defer, go, map, struct chan, else, goto, package, switch const, fallthrough, if, range, type continue, for, import, return, var 定义变量 var variablename type = value var vname1, vname2, vname3 typ

golang基础练习(一)

//遍历map package main import "fmt" func main() { x := make(map[string]int) x["zhangsan"] = 3 x["lisi"] = 4 x["wangwu"] = 5 //#丢弃值 for i,_ := range x { fmt.Println(i) } } //匿名函数 package main import "fmt" fun

golang基础归纳

1. hello-world package main import "fmt" func main(){ fmt.Println("Hello world, Go Go!"); fmt.Printf("type of Hello is %T\n", "Hello") } package main--每一个Go文件都应该在开头进行package name的声明(注:只有可执行程序的包名为main).包用于代码的封装与重用,这里

[golang基础] 局部变量初始化:=

一 基础用法 操作 := 只能用于方法内部, 声明并初始化新的变量 v := 3 但是不能用于已声明变量赋值, 下面的做法编译器会报错误"no new variables on left side of :=" var v int = 0 v := 1 通过错误可以了解到, := 操作左边必须要有新变量, 那么多个变量初始化只需要满足左边至少有一个新变量即可 err := errors.New("error1") ret, err := test_fun() 这种做