defer延迟调用

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延迟调用)