美文网首页
golang defer问题

golang defer问题

作者: 黑手党老k | 来源:发表于2019-05-06 10:45 被阅读0次

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

    相关文章

      网友评论

          本文标题:golang defer问题

          本文链接:https://www.haomeiwen.com/subject/qboloqtx.html