package main /* defer 类似其它语言中的析构函数,在函数体执行结束后 按照调用顺序的相反顺序逐个执行,先进后出, 即使函数发生严重错误也会执行,资源清理文件关闭, 支持匿名函数的调用 常用于资源清理、文件关闭、解锁以及记录时间等操作 通过与匿名函数配合可在return之后修改函数计算结果 如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer 时即已经获得了拷贝,如果不是参数则是引用某个变量的地址 Go 没有异常机制,但有 panic/recover 模式来处理错误 Panic 可以在任何地方引发,但recover只有在defer调用的函数中有效 */ import ( "fmt" ) func main1() { fmt.Println("a") defer fmt.Println("b") defer fmt.Println("c") //acb,相反顺序逐个执行,先进后出, } func main2() { fmt.Println("a") defer fmt.Println("b") defer fmt.Println("c") for i := 0; i < 3; i++ { defer fmt.Println(i) } // a 2 1 0 c b } func main3() { for i := 0; i < 3; i++ { defer func() { fmt.Println(i) }() // 3 3 3,for循环结束的时候i=3,而当main函数结束的时候开始执行defer,此时i一直是3(存在闭包) } } //go语言没有异常机制,也就是没有try catch,defer就类似于finally, //go语言的异常机制是panic/recover 模式来处理错误,Panic 可以在任何地方引发,但recover只有在defer调用的函数中有效 //函数发生错误的时候,函数已经不执行了,只能靠defer来执行一些恢复操作,所以recover只能放在defer调用的函数中才是有意义的。 func main4() { A() B() C() //AAAAAAA, panic:BBBBBBBB } func A() { fmt.Println("AAAAAAA") } func B() { panic("BBBBBBBB") //B已经panic了,C函数不执行,程序终止执行了, } func C() { fmt.Println("VCCCCCC") } func main() { A1() B1() C1() //AAAAAAA recover in B VCCCCCC //通过defer将程序从panic状态恢复回来,恢复到正常执行, } func A1() { fmt.Println("AAAAAAA") } func B1() { //恢复panic,要写在panic之前,因为如果执行了panic了后面的代码不再执行了, //那么defer就注册不了recover函数了,(defer函数是在函数执行完之后执行的,相当于只是注册了里面的一些函数) defer func() { if err := recover(); err != nil { //err为函数中出现的错误,err不为空,引发了panic,说明revcover有效,恢复panic, fmt.Println("recover in B") } }() panic("BBBBBBBB") //B已经panic了,C函数不执行,程序终止执行了, } func C1() { fmt.Println("VCCCCCC") }
slice和map是引用类型,
匿名函数不能作为顶级函数,只能够放在函数里面,
panic和recover类似于其他语言的try catch,用于异常的返回和错误的处理 。出现了错误panic,要从错误中恢复过来, 程序进入panic之后函数不再执行(类似于发生了错误跑出了异常),要想在panic之后仍然能够执行recover函数就需要用到defer,defer是不管任何情况都会执行用defer定义的函数,将recover放在defer中,并且defer要放在可能发生panic的语句之前,