我一直在努力尋找我們應用程序中的內存泄漏,并且一直在使用 pprof 工具來了解發生了什么。當我查看堆時,我不斷看到以下函數,但我不明白為什么(或是否)它實際上是一個問題。func CreateClients(raw []byte) bool { macs := []string{} conn := FormatConn(raw) if conn.Ap_Mac != "" { var wg sync.WaitGroup var array []Client c1 := make(chan Client) clients := FormatClients(conn) wg.Add(len(clients)) for _, c := range clients { go func(d Client) { defer wg.Done() c1 <- UpdateClients(d) }(c) } go func() { defer wg.Done() for { select { case client := <-c1: array = append(array, client) macs = append(macs, client.Client_Mac) } } }() wg.Wait() // Do some other stuff ...}UpdateClients 函數更新 Mongo 中的客戶端模型。當它返回時,我需要每個客戶端 - 所以我可以用 ES 索引它,另外我需要一個 mac 數組來做一些其他的事情。我已經瀏覽了在線示例,并認為這是循環通道的推薦方式。我的 pprof 堆看起來像這樣,并且在幾天內穩定增長:7.53MB of 9.53MB total (79.00%)Dropped 234 nodes (cum <= 0.05MB)Showing top 5 nodes out of 28 (cum >= 1MB) flat flat% sum% cum cum% 2MB 21.00% 21.00% 2MB 21.00% strings.Replace 1.51MB 15.89% 36.89% 1.51MB 15.89% github.com/PolkaSpots/worker/worker.func·006 1.51MB 15.87% 52.76% 1.51MB 15.87% github.com/PolkaSpots/worker/worker.func·008 1.50MB 15.75% 68.51% 1.50MB 15.75% newproc_m 1MB 10.50% 79.00% 1MB 10.50% gopkg.in/mgo.v2/bson.(*decoder).readStr有沒有更有效/推薦的方法來實現這一目標?
1 回答

郎朗坤
TA貢獻1921條經驗 獲得超9個贊
接收循環永不中斷:
for {
select {
case client := <-c1:
...
}
它沒有停止條件,沒有超時,什么都沒有——所以它會永遠掛在那里——即使你的整個函數退出。它會同時泄漏 goroutine 和通道。
最重要的是,wg.Done當這個循環退出時,你會推遲 a ,但你沒有做wg.Add匹配它。所以如果這個循環退出,你會恐慌。
您需要做的是找到某種方法來停止 for/select 循環。最簡單的方法 IMO - 在 之后添加第二個接收數據的通道wg.Wait(),但不要wg.Done()在該 goroutine 中執行。
- 1 回答
- 0 關注
- 212 瀏覽
添加回答
舉報
0/150
提交
取消