代码之家  ›  专栏  ›  技术社区  ›  Nima Mohammadi

ioutil。ReadAll导致goroutine泄漏

  •  1
  • Nima Mohammadi  · 技术社区  · 6 年前

    为什么在终止之前我有不止一个goroutine,即使我关闭了 resp.body ,而我只使用阻塞呼叫?如果我不消费 resp.Body 它只以一个goroutine结束。

    package main
    
    import (
        "fmt"
        "io/ioutil"
        "net/http"
        "runtime"
        "time"
    )
    
    func fetch() {
        client := http.Client{Timeout: time.Second * 10}
        url := "http://example.com"
        req, err := http.NewRequest("POST", url, nil)
        resp, err := client.Do(req)
        if err != nil {
            panic(err)
        }
        defer resp.Body.Close()
        _, err = ioutil.ReadAll(resp.Body)
        if err != nil {
            panic(err)
        }
    }
    
    func main() {
        fmt.Println("#Goroutines:", runtime.NumGoroutine())
        fetch()
        // runtime.GC()
        time.Sleep(time.Second * 5)
        fmt.Println("#Goroutines:", runtime.NumGoroutine())
    }
    

    输出:

    #Goroutines: 1
    #Goroutines: 3
    
    1 回复  |  直到 6 年前
        1
  •  9
  •   Peter saif iqbal    6 年前

    默认http传输 maintains a connection pool

    DefaultTransport是传输的默认实现,由DefaultClient使用。它根据需要建立网络连接,并缓存它们以供后续调用重用。

    每个连接都由至少一个goroutine管理。但这不是泄密,你只是不耐烦而已。如果您等待的时间足够长,您将看到连接最终关闭,goroutine也会消失。默认空闲超时为90秒。

    如果要尽快关闭连接,请设置 http.Request.Close http.Transport.DisableKeepAlives 为真。