Ответ
Да, несмотря на наличие автоматического сборщика мусора (GC), в Go могут возникать утечки памяти. GC освобождает только ту память, на которую больше нет ссылок из работающего кода. Утечка происходит, когда ненужные объекты всё ещё остаются достижимыми (имеют ссылки), и GC не может их удалить.
Основные причины утечек памяти в Go:
-
Зависшие горутины (Goroutine Leaks) Если горутина блокируется навсегда (например, при ожидании данных из канала, в который никто никогда не напишет), все объекты, на которые она ссылается, никогда не будут освобождены.
// Горутина заблокируется навсегда, если в канал ch никто не отправит данные go func() { data := <-ch // ... }()
-
Глобальные коллекции Данные, добавленные в глобальные переменные (например,
map
илиslice
), будут существовать в течение всего времени жизни приложения, если их оттуда не удалять. Бесконтрольное наполнение таких коллекций — классическая утечка.var globalCache = make(map[string][]byte) func AddToCache(key string, value []byte) { globalCache[key] = value // Память будет расти, если кэш не чистить }
-
Неправильное использование срезов (Slices) Срез, который является частью большого базового массива, удерживает ссылку на весь массив. Даже если вы используете маленький срез, сборщик мусора не сможет освободить память изначального большого массива.
bigArray := make([]byte, 1024*1024) // 1MB // smallSlice использует всего 10 байт, но удерживает в памяти весь 1MB массив smallSlice := bigArray[:10]
-
Незакрытые ресурсы Соединения с базой данных, файловые дескрипторы или сетевые подключения должны явно закрываться (
defer file.Close()
). Если этого не делать, связанные с ними ресурсы не освободятся. -
Использование CGO Память, выделенная в коде на языке C через CGO, не управляется сборщиком мусора Go. Её нужно освобождать вручную с помощью
C.free()
.
Для диагностики утечек в Go используется встроенный инструмент pprof.