初级会员
  • 第 56881 位会员
  • TonoT
  • xuezonggui
  • 2020-09-28 16:35:56
  • Offline
  • 20 38

最近分享的资源

    暂无

最近发布的项目

    暂无

最近的评论

  • 不错,收藏了
  • #12 @zhanghaoliang 就这个问题,我做了一些总结,https://studygolang.com/articles/33108?fr=sidebar
  • #2 @jarlyyn 嗯,我知道原因了,我以为forrange会重新分配变量的,这个地方我在理解一下
  • 以下为实例展示: ```go func main() { for i := 0; i < 2; i++ { _, err := http.Get("https://www.baidu.com") if err != nil { panic(err) } //io.Copy(ioutil.Discard, resp.Body) //resp.Body.Close() } } ``` ![](https://github.com/TonoT/allimages/blob/main/1.png?raw=true) ```go func main() { for i := 0; i < 2; i++ { resp, err := http.Get("https://www.baidu.com") if err != nil { panic(err) } io.Copy(ioutil.Discard, resp.Body) //resp.Body.Close() } } ``` ![](https://github.com/TonoT/allimages/blob/main/2.png?raw=true)
  • #1 @avtion 这两天看了下源码并且实验了一下,得出以下结论: 1. `resp.body.close()` 释放io资源,防止内存泄漏 2. body全部读取完毕(io.Copy(os.Stdout, resp.Body)),实现tcp的复用 `resp.body`本质上是一个io流,它在系统中占用了部分的内存资源,go语言的gc并不会对其进行释放,所以需要我们手动释放。 `tcp的多路复用` ```go // Before looping back to the top of this function and peeking on // the bufio.Reader, wait for the caller goroutine to finish // reading the response body. (or for cancellation or death) select { case bodyEOF := <-waitForBodyRead: pc.t.setReqCanceler(rc.req, nil) // before pc might return to idle pool alive = alive && bodyEOF && !pc.sawEOF && pc.wroteRequest() && tryPutIdleConn(trace) //tcp复用 if bodyEOF { eofc <- struct{}{} } case <-rc.req.Cancel: alive = false pc.t.CancelRequest(rc.req) case <-rc.req.Context().Done(): alive = false pc.t.cancelRequest(rc.req, rc.req.Context().Err()) case <-pc.closech: alive = false } ``` 当bodyEOF为true是才会走tcp复用(alive等先不管),那么bodyEOF什么时候才会为true ```go fn: func(err error) error { isEOF := err == io.EOF //io流被读取完 waitForBodyRead <- isEOF if isEOF { <-eofc // see comment above eofc declaration } else if err != nil { if cerr := pc.canceled(); cerr != nil { return cerr } } return err }, ``` 因此需要对body读取完毕。