请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

for循环里面的defer

Loop1:
for {
resp, err = http.Get(url)
defer resp.Body.Close()
if err != nil {
logger.Info(err)
} else {
body, err = ioutil.ReadAll(resp.Body)
if resp.StatusCode == 200 {
break Loop1
}
logger.Info(err)
}
logger.Info(err)
time.Sleep( 5 * time.Second)
}

老师,for循环里这样写defer,goland会提示可能发生资源泄露,应该怎么写更合理一点呢

正在回答 回答被采纳积分+3

插入代码

1回答

ccmouse 2021-07-20 21:54:16

的确会发生泄漏。defer的运行时机是函数返回之前,而不是大括号之前。所以这些Body要等到整个for退出,函数结束才能Close。我来演示一下更好的写法,注意Loop:这些,我们也尽量不要,利用函数来控制跳转以及defer的执行时机。

func getWithRetry(url string) []byte {

     for {

         body, err := get(url)

         if err == nil {

              return body

         }

         logger.Info(err) // 这里应该使用Error或Warning

         time.Sleep(5 * time.Second)

     }

}


func get(url string) ([]byte, error) {

     resp, err := http.Get(url)

     // 先检查错误

     if err != nil {

          return nil, err

     }

     // 再defer Body.Close()

     defer resp.Body.Close()

    

     body, err := ioutil.ReadAll(resp.Body)

     fmt.Print(body) // 这里似乎即使出错也想要打印body。不然的话我们应该先判断StatusCode

     if resp.StatusCode != 200 {

          return nil, fmt.Errorf("bad status: %d", resp.StatusCode)

     }

     return body, nil

}


0 回复 有任何疑惑可以回复我~
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信