golang defer问题

2019-05-06  本文已影响0人  黑手党老k

一 函数中间使用defer

func returnValues() int {
    var result int 
    defer func() {
       result++
      fmt.Println("defer")
}()
return result
}

func nameReturnValue() (result int) {
    defer func(){
        result++
        fmt.Println("defer")
  }()
return result
}

// 在这里上面的方法输出0,下面的方法输出1,因为上面使用的匿名返回值,下面使用的命名返回值
// defer的执行逻辑(匿名返回值为例)
1. 将result赋值给返回值,相当于go自动创建一个返回值returnValue,然后将result赋值给returnValue
2. 检查defer,
3. 返回刚刚创建的returnValue

再来看几个demo

func f() (result int) {
    defer func() {
        result++
    }()
    return 0
}

func f2() (r int) {
    t := 5
    defer func() {
        t = t + 5
    }()
    return t
}

func f3() (r int) {
    defer func(r int) {
        r = r + 5
    }(r)
    return 1
}

func f4() (r int) {
    defer func() {
        r = r + 5
    }()
    return 1
}
// 这里最后的结果是1,5, 1, 6
// f()相当于
func f() (result int) {
        var result = 0
       func() {
        result++   // 1
    }()
    return 
}
// f2()相当于
func f2() (r int) {
    t := 5
        r = t
    func() {
        t = t + 5
    }()
    return
}
r已经赋值无论如何变更t,r的值都不会再次发生改变

// f3()相当于
func f() (r int) {
     r = 1  //给返回值赋值
     func(r int) {        //这里改的r是传值传进去的r,不会改变要返回的那个r值
          r = r + 5
     }(r)
     return        //空的return
}

// f4()相当于
func f4() (r int) {
      var r = 1
      func() {
        r = r + 5   // 6
    }()
    return 
}

二 for循环中间使用defer

func deferInLoops(){
    for i:=0;i<100;i++{
        f, _:= os.Open("xxx")
        defer f.Close()
  }
}
// 这里需要注意defer的执行是需要额外的开销的,对其后需要的参数进行内存拷贝,还需要对defer结构进行压栈出栈操作

三 判断执行没有err之后,再defer释放资源

resp, err := http.Get(url)
// 先判断操作是否成功
if err != nil {
    return err
}
// 如果操作成功,再进行Close操作
defer resp.Body.Close()

四 调用os.Exit的时候defer不会被执行

func deferExit() {
    defer func() {
        fmt.Println("defer")
  }()
os.Exit(0)
}
// 这种情况defer不会被执行
上一篇下一篇

猜你喜欢

热点阅读