TGViewer
Библиотека Go (Golang) разработчика Библиотека Go (Golang) разработчика @golang_lib · 2.7K subscribers
Post #698 743
♻️ sync.Pool: Как перестать кормить Garbage Collector'а

Представьте, что вы работаете в кофейне. Приходит клиент, вы покупаете новую керамическую кружку, наливаете кофе, отдаете клиенту. Он выпивает кофе и... выбрасывает кружку в мусорку. А вы идете покупать новую.

Звучит как бред? Но именно так ведет себя ваш код, когда вы создаете буферы make([]byte, 4096) внутри HTTP-хендлера, который обрабатывает 10 000 запросов в секунду. Вы непрерывно выделяете память, а Garbage Collector (тот самый уборщик из прошлых постов) сходит с ума, пытаясь всё это собрать. Сервис тормозит, CPU кипит.

Решение проблемы sync.Pool. Это полка с чистыми кружками.

Как это работает:
Вместо того чтобы создавать объект с нуля, вы просите его у пула (Get). Попользовались - помыли - вернули в пул (Put).

✅ Как это выглядит в коде:


var bufPool = sync.Pool{
// Эта функция вызовется ТОЛЬКО если пул пуст
// и нам действительно нужно создать новый объект
New: func() any {
// Выделяем память один раз!
return new(bytes.Buffer)
},
}

func HandleRequest(w http.ResponseWriter, r *http.Request) {
// 1. Берем буфер из пула (приводим тип, так как Pool возвращает any)
buf := bufPool.Get().(*bytes.Buffer)

// 2. ОБЯЗАТЕЛЬНО: Возвращаем буфер в пул при выходе из функции
defer bufPool.Put(buf)

// 3. КРИТИЧЕСКИ ВАЖНО: Очищаем буфер перед использованием!
buf.Reset()

// ... используем buf для json.Marshal или io.Copy ...
buf.WriteString("hello, world")
}



🔥 Нюансы для Senior-ов (Ловушки sync.Pool):

1. Грязные кружки (Утечка данных).
Если вы забыли сделать buf.Reset() перед тем как положить буфер обратно (или сразу после того, как достали), следующий гость получит кружку с остатками чужого кофе. В мире микросервисов это значит, что ответ одному пользователю может случайно содержать кусок JSON-а с приватными данными предыдущего пользователя. Это жесточайшая уязвимость.
2. Это не кэш для бизнес-данных!
Многие думают: "О, круто, положу-ка я туда настройки из БД, чтобы не ходить за ними каждый раз".
Нет. Garbage Collector в Go имеет полное право (и делает это) полностью очистить весь sync.Pool во время сборки мусора. Пул может опустеть в любую миллисекунду. Он предназначен только для переиспользования пустой памяти, а не для хранения состояния.
3. Под капотом: Никаких блокировок (почти).
Зачем использовать sync.Pool, а не написать свой кэш на каналах или мьютексах?
Потому что sync.Pool гениально оптимизирован под планировщик Go (GMP). Он хранит локальный пул для каждого логического ядра (P). Когда горутина просит объект, она берет его из пула своего ядра вообще без блокировки (lock-free). Мьютексы включаются только тогда, когда локальный пул пуст и нужно "украсть" объект у соседнего ядра.

Используйте sync.Pool для []byte, bytes.Buffer, сложных структур парсинга - и ваши графики CPU станут плоскими, как кардиограмма после дедлайна.

Кто уже внедрял sync.Pool и ловил баги с нестертыми данными? Признавайтесь 👇

#golang #performance #memory #underhood #bestpractices

📲 Мы в MAX

👉 @golang_lib
  • 👍 6
  • 🔥 2
More from @golang_lib
  1. Sep 22, 2026🔴AI кодинг интервью с разработчиком из международного FinTech в четверг в 19:00 ДА! Вайбк…
  2. Sep 21, 2026📢 sync.Cond: Как разбудить 10 000 горутин одним вызовом (и не сломать планировщик) Предст…
  3. Sep 17, 2026🔎 pprof: Как найти функцию, которая жрет 80% CPU Сервис на проде внезапно упирается в пол…
  4. Sep 7, 2026🗺️ sync.Map: Почему эта «серебряная пуля» иногда пробивает дно производительности Как тол…
  5. Sep 2, 2026☢️ Пакет unsafe: Взламываем систему типов Go Пакет unsafe - это легальный способ сказать к…
  6. Sep 1, 2026🔴 Тестовое собеседование с Go Senior с опытом работы в Яндексе, EPAM и Uzum в этот четвер…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →