Goroutines内存泄漏

Goroutines内存泄漏,go,memory-leaks,channel,goroutine,Go,Memory Leaks,Channel,Goroutine,UPD:重构代码,没有任何更改 我很抱歉这个函数有内存泄漏,但我不知道在哪里 func CheckProxySOCKS(prox string, c chan QR) (err error) { //Sending request through proxy dialer, _ := proxy.SOCKS5("tcp", prox, nil, proxy.Direct) timeout := time.Duration(5 * time.Second) htt

UPD:重构代码,没有任何更改

我很抱歉这个函数有内存泄漏,但我不知道在哪里

func CheckProxySOCKS(prox string, c chan QR) (err error) {

    //Sending request through proxy
    dialer, _ := proxy.SOCKS5("tcp", prox, nil, proxy.Direct)
    timeout := time.Duration(5 * time.Second)
    httpClient := &http.Client{Timeout: timeout, Transport: &http.Transport{Dial: dialer.Dial}}
    res, err := httpClient.Get("https://api.ipify.org?format=json")

    if err != nil {

        c <- QR{Addr: prox, Res: false}
        return
    }

    _, err = ioutil.ReadAll(res.Body)
    res.Body.Close()
    if err != nil {
        return
    }

    c <- QR{Addr: prox, Res: true}
    return
}
func CheckProxySOCKS(prox字符串,c chan QR)(错误){
//通过代理发送请求
拨号器,u:=proxy.SOCKS5(“tcp”,prox,nil,proxy.Direct)
超时:=时间.持续时间(5*时间.秒)
httpClient:=&http.Client{超时:超时,传输:&http.Transport{Dial:dialer.Dial}
res,err:=httpClient.Get(“https://api.ipify.org?format=json")
如果错误!=零{

c您的问题在于没有关闭响应主体,在这行:

_, err := httpClient.Get("https://api.ipify.org?format=json")
获取响应变量并在“延迟”中关闭主体,如下所示:

r, err := httpClient.Get("https://api.ipify.org?format=json")
if err != nil {
    c <- QR{Addr: prox, Res: false}
    return
}
defer r.Body.Close()

c <- QR{Addr: prox, Res: true}
r,err:=httpClient.Get('https://api.ipify.org?format=json")
如果错误!=零{

c您的问题在于没有关闭响应主体,在这行:

_, err := httpClient.Get("https://api.ipify.org?format=json")
获取响应变量并在“延迟”中关闭主体,如下所示:

r, err := httpClient.Get("https://api.ipify.org?format=json")
if err != nil {
    c <- QR{Addr: prox, Res: false}
    return
}
defer r.Body.Close()

c <- QR{Addr: prox, Res: true}
r,err:=httpClient.Get('https://api.ipify.org?format=json")
如果错误!=零{

c您并不总是关闭连接,您使用的是新客户端并传输每个请求。如果放弃传输,则放弃空闲池中的所有连接,从而泄漏这些资源

默认情况下,传输缓存连接以供将来重复使用。这可能会在访问多个主机时留下许多打开的连接。可以使用传输的CloseIdleConnections方法以及MaxIdleConsperHost和DisableKeepAlives字段来管理此行为

传输应该被重用,而不是根据需要创建。传输对于多个goroutine并发使用是安全的


如果没有错误,请始终关闭响应正文,并始终重新使用传输。

您并非总是关闭连接,而是使用新客户端并传输每个请求。如果放弃传输,则放弃空闲池中的所有连接,从而泄漏这些资源

默认情况下,传输缓存连接以供将来重复使用。这可能会在访问多个主机时留下许多打开的连接。可以使用传输的CloseIdleConnections方法以及MaxIdleConsperHost和DisableKeepAlives字段来管理此行为

传输应该被重用,而不是根据需要创建。传输对于多个goroutine并发使用是安全的


始终在没有错误时关闭响应正文,并始终重复使用传输。

在调用
代理时,您应该检查错误。SOCKS5
此外,文档还说您应该关闭调用
Get
的响应。目前不确定这是否是您的问题,但您可能希望绑定该变量并调用其
close方法。我想说一些比前面的注释更强的内容。Get成功返回时,应用程序必须关闭响应正文。这是您看到的问题的原因之一,可能也是唯一原因。请关闭响应正文,不要为每个请求创建新的客户端(或者更准确地说,新的传输)。每个传输都维护自己的连接池,并且由于您没有禁用“保持活动”,您最终会得到大量从未重用的空闲连接。@Peter我更改了如下代码
httpClient:=&http.Client{Timeout:Timeout,Transport:&http.Transport{DisableKeepAlives:true,Dial:dialer.Dial}
但是它帮不上忙。或者我做错了?也许你有一个例子?你应该在调用
代理时检查你的错误。SOCKS5
文档还说你应该关闭调用
Get
的响应。目前不确定这是否是你的问题,但你可能想绑定该变量并调用它的
close
方法。我想说一些比前面的评论更有力的话。当Get成功返回时,应用程序必须关闭响应主体。这是您看到的问题的原因之一,也可能是唯一原因。请关闭响应主体,不要为每个请求创建新的客户端(或者更准确地说,新的传输)。每个传输都维护自己的连接池,并且由于您没有禁用“保持活动”,您最终会得到大量从未重用的空闲连接。@Peter我更改了如下代码
httpClient:=&http.Client{Timeout:Timeout,Transport:&http.Transport{DisableKeepAlives:true,Dial:dialer.Dial}
但这没用。或者我做错了?也许你有一个例子?我按照你的建议重构了代码,但没有任何变化。请移动:`res.Body.Close()`在ioutil.ReadAll上面,它不会修复内存泄漏,但只是为了确保。别忘了在它之前添加
defer
。我按照您的建议重构了代码,但没有任何更改。请移动:`res.Body.Close()`在ioutil.ReadAll上面,它不会修复内存泄漏,只是为了确保。不要忘记在它之前添加
defer