golang defer问题

黑手党老k · · 728 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

一 函数中间使用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不会被执行

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:黑手党老k

查看原文:golang defer问题

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

728 次点击  
加入收藏 微博
上一篇:Golang状态模式
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传