package main
import (
"errors"
"fmt"
"io"
"net/http"
"os"
"sync"
)
type Test struct{
name string
}
//声明一个互斥锁
var lock sync.Mutex
var ErrDivByZero = errors.New("division by zero")
func (t *Test)Close() {
fmt.Println(t.name, " closed")
}
func Close(t Test) {
fmt.Println(t.name, " closed")
}
func test(x int){
defer func() {
msg := recover()
fmt.Println(msg)
}()
defer println("a")
defer println("b")
defer func() {
fmt.Println(100/x)
}()
defer println("c")
}
func testDeferFunc() {
x,y := 10,20
//延迟调用参数在注册时求值或复制
defer func(i int) {
fmt.Println("defer " ,i ,y)
}(x)
x += 10
y += 100
fmt.Println("x = ", x, " y = ", y)
}
func testLock() {
lock.Lock()
lock.Unlock()
}
func testDeferLock() {
lock.Lock()
defer lock.Unlock()
}
func foo() (i int) {
i = 0
//在延迟调用注册时求职和复制
//out i=0
//defer func(i int) {
// fmt.Println(i)
//}(i)
//闭包,保存外部函数的变量
//out i=2
defer func() {
fmt.Println(i)
}()
return 2
}
func foo1(a,b int) (i int, err error) {
defer fmt.Println("the first defer err",err)
defer func(err error) {
fmt.Println("the second defer err",err)
}(err)
defer func() {
fmt.Println("the third defer err",err)
}()
if(b == 0){
err = errors.New("divided by zero!")
return
}
i = a/b
//这种return会将相应的返回值进行返回
return
}
func testRun() {
var run func() = nil
defer run()
fmt.Println("runs")
}
func do() error {
//发起get请求
res, err := http.Get("http://www.google.com")
defer res.Body.Close()
if err != nil {
return err
}
//
return nil
}
func do1() error {
res, err := http.Get("http://www.google.com")
if res != nil {
defer res.Body.Close()
}
if err != nil {
return err
}
//code
return nil
}
func doFile() error {
f, err := os.Open("a.txt")
if err != nil {
fmt.Println(err)
return err
}
////由于文件关闭时也会出现错误,所以在使用defer进行延迟关闭
//if f != nil {
// defer f.Close()
//}
if f != nil {
defer func(){
if err := f.Close(); err != nil {
}
}()
}
return nil
}
func doFile1() (err error) {
f, err := os.Open("a.txt")
if err != nil {
return err
}
if f != nil {
defer func() {
if ferr := f.Close(); ferr != nil {
err = ferr
}
}()
}
return nil
}
func doFileClose() error {
f, err := os.Open("book.txt")
if err != nil {
return err
}
if f != nil {
defer func(f io.Closer) {
if err := f.Close(); err != nil {
fmt.Printf("defer close book.txt err %v\n",err)
}
}(f)
}
f, err = os.Open("another_book.txt")
if err != nil {
return err
}
if f != nil {
defer func(f io.Closer) {
if err := f.Close(); err != nil {
fmt.Printf("defer close another_book.txt err %v\n",err)
}
} (f)
}
return nil
}
func deferpanic() {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}()
var ch chan int = make(chan int, 10)
close(ch)
ch <- 1
}
func testPanic() {
//如果有多个panic指挥捕获最后的panic
defer func() {
fmt.Println(recover())
}()
defer func() {
panic("defer panic")
}()
panic("test panic")
}
//捕获函数recover只有在延迟函数内直接调用才有效
func testRecover() {
//捕获函数只有在延迟函数内直接调用才会有效
defer func() {
fmt.Println("defer func")
fmt.Println(recover())
}()
defer recover()//无效
defer fmt.Println(recover())//无效
defer func() {
//err := recover()
//fmt.Println(err)
func() {
fmt.Println("defer recover")//虽然执行了但是recover未执行
recover()//无效
}()
}()
panic("test panic")
}
func div(x,y int)(int, error){
if y == 0 {
return 0, ErrDivByZero
}
z := x/y
return z, nil
}
func divRecover() {
defer func() {
fmt.Println(recover())
}()
switch z,err := div(10, 0); err {
case nil:
fmt.Println(z)
case ErrDivByZero:
fmt.Println(err)
}
}
func main() {
//ts := []Test{{"a"}, {"b"} ,{"c"}}
//for _,t := range ts {
// //1
// //由于t为局部变量,且为同一个变量,当从ts中读出值的时候,t最终会保留最后一个对象的引用
// //所以输出结果总是c closed
// //此时的t相当于this指针
// //defer t.Close()
// //2
// //对于将struct作为函数参数而言,go再进行函数调用时,会将参数的拷贝保存起来,执行defer时自然就正确了
// //defer Close(t)
// //3
// //使用t1对t进行拷贝之后再次defer时,t1保存了当前层的引用
// t1 := t
// defer t1.Close()
//}
//test(0)
//testDeferFunc()
//滥用defer可能导致性能问题
//func() {
// t1 := time.Now()
// for i:=0;i<10000;i++ {
// testLock()
// }
// elapsed := time.Since(t1)
// fmt.Println("testLock elapsed = ", elapsed)
//} ()
//
//func() {
// t2 := time.Now()
// for i:=0;i<10000;i++ {
// testDeferLock()
// }
// elapesd := time.Since(t2)
// fmt.Println("testDeferLock elapsed = ", elapesd)
//} ()
//
//foo()
//
//foo1(1,0)
//defer func() {
// if err := recover(); err != nil {
// fmt.Println("error: ", err)
// }
//}()
//testRun()
//do()
//do1()
//doFile()
//doFile1()
//err := doFileClose()
//fmt.Println(err)
//向已经关闭的通道发送数据抛出异常
//deferpanic()
//testPanic()
//testRecover()
divRecover()
}
defer延迟调用
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...