Go语言中bytes.Buffer导致内存泄漏:客户端如何正确关闭响应体避免内存占用居高不下?

Go语言中bytes.Buffer导致内存泄漏:客户端如何正确关闭响应体避免内存占用居高不下?

go语言bytes.Buffer内存泄漏分析及解决方案

Go语言中使用bytes.Buffer进行字符串拼接,若处理不当,可能导致内存泄漏。本文分析一个案例,解释bytes.Buffer(间接地,通过其内部的bytes.makeSlice)如何导致内存占用居高不下,以及如何解决。

案例描述:

服务端使用Fiber框架,/test路由处理请求时创建bytes.Buffer,写入大量数据(100万次“123”字符串)。客户端并发发送500个请求。使用go tool pprof分析,发现bytes.makeSlice占用大量内存且未释放。

立即学习go语言免费学习笔记(深入)”;

服务端代码片段 (简化):

package main  import (     "bytes"     "github.com/gofiber/fiber/v2" )  func main() {     app := fiber.New()     app.Get("/test", func(c *fiber.Ctx) error {         buffer := bytes.NewBufferString("")         for i := 0; i < 1000000; i++ {             buffer.WriteString("123")         }         return c.SendString(buffer.String())     })     app.Listen(":9001") }

客户端代码片段 (简化):

package main  import (     "fmt"     "net/http"     "sync" )  func main() {     var wg sync.WaitGroup     for i := 0; i < 500; i++ {         wg.Add(1)         go func() {             defer wg.Done()             resp, err := http.Get("http://localhost:9001/test")             if err != nil {                 fmt.Println("Error:", err)                 return             }             // 关键缺失:resp.Body.Close()             // ... 处理resp.Body ...         }()     }     wg.Wait() }

问题根源:

客户端代码缺少resp.Body.Close()。resp.Body是io.ReadCloser,包含从服务端接收的数据。不调用Close(),底层连接和缓冲区不会释放,导致内存泄漏。bytes.makeSlice高内存占用是因为服务端生成的bytes.Buffer数据被客户端接收但未正确关闭。即使服务端代码无内存管理错误,客户端未关闭响应体也会造成泄漏。

解决方案:

在客户端代码中添加resp.Body.Close():

resp, err := http.Get("http://localhost:9001/test") if err != nil {     fmt.Println("Error:", err)     return } defer resp.Body.Close() // 添加此行 // ... 处理resp.Body ...

使用defer resp.Body.Close()确保函数执行完毕后关闭resp.Body,释放资源,避免内存泄漏。 这才是解决bytes.makeSlice内存占用问题的关键。 问题并非bytes.Buffer本身,而是资源未被正确释放。

以上就是Go语言中bytes.Buffer导致内存泄漏:客户端如何正确关闭响应体避免

© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享