登录
首页 >  Golang >  Go问答

内存泄漏问题与 client.Do()

来源:stackoverflow

时间:2024-02-24 09:03:26 104浏览 收藏

从现在开始,我们要努力学习啦!今天我给大家带来《内存泄漏问题与 client.Do()》,感兴趣的朋友请继续看下去吧!下文中的内容我们主要会涉及到等等知识点,如果在阅读本文过程中有遇到不清楚的地方,欢迎留言呀!我们一起讨论,一起学习!

问题内容

getapidata函数用于获取html字符串,并且需要每5秒调用一次。我使用 runtime.readmemstats 函数检查了内存使用情况。

如下面的输出所示,内存缓慢增加但从未减少。

alloc = 1 mib   totalalloc = 2 mib      sys = 71 mib    numgc = 1
...
alloc = 3 mib   totalalloc = 4 mib      sys = 71 mib    numgc = 1
...
alloc = 3 mib   totalalloc = 6 mib      sys = 71 mib    numgc = 2
alloc = 2 mib   totalalloc = 7 mib      sys = 71 mib    numgc = 3
...
alloc = 3 mib   totalalloc = 9 mib      sys = 71 mib    numgc = 3
...
alloc = 3 mib   totalalloc = 10 mib     sys = 71 mib    numgc = 4

我为我的问题制作了示例代码。我应该怎么做才能修复内存泄漏?

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "runtime"
    "time"
)

func getAPIData() (string, error) {
    req, err := http.NewRequest("GET", "https://google.com/", nil)
    if err != nil {
        //fmt.Println(err.Error())
        return "", err
        //panic(err)
    }
    req.Header.Add("User-Agent", "Mozilla/5.0")

    client := &http.Client{Timeout: 3 * time.Second}
    resp, err := client.Do(req) // cuase of memory leak
    if err != nil {
        fmt.Println(err.Error())
        return "", err
        //panic(err)
    }
    defer resp.Body.Close()

    bytes, err2 := ioutil.ReadAll(resp.Body)
    if err2 != nil {
        fmt.Println(err2.Error())
        return "", err2
        //panic(err)
    }
    return string(bytes), nil
}

func PrintMemUsage() {
    var m runtime.MemStats
    runtime.ReadMemStats(&m)

    fmt.Printf("Alloc = %v MiB", bToMb(m.Alloc))
    fmt.Printf("\tTotalAlloc = %v MiB", bToMb(m.TotalAlloc))
    fmt.Printf("\tSys = %v MiB", bToMb(m.Sys))
    fmt.Printf("\tNumGC = %v\n", m.NumGC)
}

func bToMb(b uint64) uint64 {
    return b / 1024 / 1024
}
func main() {
    for range time.Tick(5 * time.Second) {
        _, _ = getAPIData()
        PrintMemUsage()
    }
}

正确答案


可能不是内存泄漏的根源,但在处理 http.clients 时,docs 建议:

因此,在您的示例中,更新您的 api 签名以传入客户端:

func getapidata(client *http.client) (string, error)

并将(单个)客户端创建移至 main

func main() {

    cli := &http.Client{Timeout: 3 * time.Second} // create once ...

    for range time.Tick(5 * time.Second) {
        _, _ = getAPIData(cli)   // ... reuse many times
        PrintMemUsage()
    }
}

本篇关于《内存泄漏问题与 client.Do()》的介绍就到此结束啦,但是学无止境,想要了解学习更多关于Golang的相关知识,请关注golang学习网公众号!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>