for循环里面的defer
来源:8-1 defer调用

小肉包哥
2021-07-16
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会提示可能发生资源泄露,应该怎么写更合理一点呢
1回答
-
ccmouse
2021-07-20
的确会发生泄漏。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
}
00
相似问题