Go語言中bytes.Buffer導致內(nèi)存泄漏:客戶端如何正確關閉響應體避免內(nèi)存占用居高不下?

Go語言中bytes.Buffer導致內(nèi)存泄漏:客戶端如何正確關閉響應體避免內(nèi)存占用居高不下?

go語言bytes.Buffer內(nèi)存泄漏分析及解決方案

Go語言中使用bytes.Buffer進行字符串拼接,若處理不當,可能導致內(nèi)存泄漏。本文分析一個案例,解釋bytes.Buffer(間接地,通過其內(nèi)部的bytes.makeSlice)如何導致內(nèi)存占用居高不下,以及如何解決。

案例描述:

服務端使用Fiber框架,/test路由處理請求時創(chuàng)建bytes.Buffer,寫入大量數(shù)據(jù)(100萬次“123”字符串)。客戶端并發(fā)發(fā)送500個請求。使用go tool pprof分析,發(fā)現(xiàn)bytes.makeSlice占用大量內(nèi)存且未釋放。

立即學習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,包含從服務端接收的數(shù)據(jù)。不調(diào)用Close(),底層連接和緩沖區(qū)不會釋放,導致內(nèi)存泄漏。bytes.makeSlice高內(nèi)存占用是因為服務端生成的bytes.Buffer數(shù)據(jù)被客戶端接收但未正確關閉。即使服務端代碼無內(nèi)存管理錯誤,客戶端未關閉響應體也會造成泄漏。

解決方案:

在客戶端代碼中添加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()確保函數(shù)執(zhí)行完畢后關閉resp.Body,釋放資源,避免內(nèi)存泄漏。 這才是解決bytes.makeSlice內(nèi)存占用問題的關鍵。 問題并非bytes.Buffer本身,而是資源未被正確釋放。

以上就是Go語言中bytes.Buffer導致內(nèi)存泄漏:客戶端如何正確關閉響應體避免

? 版權聲明
THE END
喜歡就支持一下吧
點贊5 分享