Go без тормозов: 11 промтов для конкурентности, gRPC и профилирования высоконагруженных сервисов
Каждый Go-разработчик рано или поздно сталкивается с выгоранием от рутинных задач: написание шаблонного кода для горутин, отладка gRPC-сервисов, поиск утечек памяти. По данным опроса Go Developer Survey 2025, более 60% респондентов используют Go для микросервисов и высоконагруженных систем. Но даже опытные инженеры тратят до 30% времени на boilerplate и диагностику. В этой подборке я собрал 11 промтов, которые превращают LLM в вашего персонального ассистента по конкурентности, gRPC и профилированию. Каждый промт — это готовый инструмент, проверенный в реальных проектах. Вы можете использовать их в ChatGPT, Claude или любом другом чате. Главное — давать контекст и проверять результат.
Базовые промты: от горутин до контекста
1. Генерация паттерна Worker Pool с ограничением
Задача: Быстро создать пул воркеров для обработки задач с контролем количества горутин.
Промт:
Напиши на Go реализацию worker pool с ограничением количества воркеров. Функция должна принимать количество воркеров, канал задач и функцию-обработчик. Добавь контекст для отмены. Поясни, как избежать утечки горутин.
Пример результата:
func WorkerPool(ctx context.Context, workers int, tasks <-chan Task, handler func(Task)) {
var wg sync.WaitGroup
for i := 0; i < workers; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for {
select {
case task, ok := <-tasks:
if !ok { return }
handler(task)
case <-ctx.Done():
return
}
}
}()
}
wg.Wait()
}
Пояснение: Промт заставляет LLM сгенерировать безопасный код с context и WaitGroup. Вы сразу получаете готовый шаблон, который можно адаптировать.
2. Обработка ошибок в горутинах
Задача: Не потерять ошибки, возникающие в параллельных горутинах.
Промт:
Как правильно собирать ошибки из нескольких горутин в Go? Напиши пример с errgroup и без него. Сравни подходы.
Пример результата:
g, ctx := errgroup.WithContext(context.Background())
for i := 0; i < 10; i++ {
i := i
g.Go(func() error {
return process(ctx, i)
})
}
if err := g.Wait(); err != nil {
log.Fatal(err)
}
Пояснение: errgroup из golang.org/x/sync — стандарт для таких задач. Промт помогает вспомнить синтаксис и избежать классической ошибки с замыканием переменной цикла.
3. Graceful shutdown для HTTP-сервера
Задача: Корректно завершить работу сервера при получении сигнала.
Промт:
Покажи пример graceful shutdown для net/http сервера на Go с обработкой SIGINT и SIGTERM. Учти таймаут на завершение.
Пример результата:
srv := &http.Server{Addr: ":8080"}
go func() {
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
log.Fatalf("listen: %s", err)
}
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Fatal("Server forced to shutdown:", err)
}
Пояснение: Классический паттерн, который часто забывают. Промт напоминает про context.WithTimeout и signal.Notify.
Продвинутые промты: gRPC и микросервисы
4. Генерация gRPC-сервиса с interceptors
Задача: Создать gRPC-сервер с логированием, аутентификацией и recovery.
Промт:
Сгенерируй на Go gRPC-сервер с unary interceptor для логирования, аутентификации по JWT и recovery от паник. Используй grpc-go. Приведи полный код.
Пример результата:
func loggingInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
start := time.Now()
resp, err := handler(ctx, req)
log.Printf("method=%s duration=%s error=%v", info.FullMethod, time.Since(start), err)
return resp, err
}
// Аналогично для auth и recovery
Пояснение: Промт экономит часы на написание boilerplate для middleware. Вы получаете готовые interceptors, которые можно комбинировать.
5. Балансировка нагрузки в gRPC
Задача: Настроить клиентскую балансировку между несколькими экземплярами сервиса.
Промт:
Как реализовать client-side load balancing в gRPC на Go? Покажи пример с resolver и round_robin. Учти обнаружение сервисов через DNS.
Пример результата:
conn, err := grpc.Dial(
"dns:///my-service:50051",
grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy":"round_robin"}`),
grpc.WithInsecure(),
)
Пояснение: gRPC поддерживает балансировку из коробки, но синтаксис редко запоминается. Промт даёт рабочий пример с DNS-резолвером.
6. Трассировка в микросервисах
Задача: Добавить распределённую трассировку в gRPC-сервисы.
Промт:
Покажи, как интегрировать OpenTelemetry в gRPC-сервер и клиент на Go. Настрой экспорт трейсов в Jaeger.
Пример результата:
import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
server := grpc.NewServer(grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()))
Пояснение: OpenTelemetry — стандарт для observability. Промт помогает быстро подключить инструментацию без чтения длинной документации.
Экспертные промты: профилирование и оптимизация
7. Поиск утечек горутин
Задача: Обнаружить и устранить утечку горутин в продакшене.
Промт:
Как найти утечку горутин в Go-приложении? Опиши методику с pprof: какие профили смотреть, как интерпретировать. Приведи пример кода, который течёт, и как его исправить.
Пример результата:
// Утечка: горутина блокируется на канале без читателя
func leak() {
ch := make(chan int)
go func() { ch <- 1 }() // горутина висит
}
// Исправление: использовать буферизованный канал или context
Пояснение: pprof — мощный инструмент, но требует навыка. Промт даёт пошаговый алгоритм: запустить с http.ListenAndServe("localhost:6060", nil), снять /debug/pprof/goroutine?debug=2.
8. Анализ CPU-профиля
Задача: Понять, какая функция съедает CPU.
Промт:
У меня есть CPU-профиль из pprof. Как его анализировать? Покажи команды для top, list, web. На что обращать внимание?
Пример результата:
go tool pprof -http=:8080 cpu.prof
# В браузере смотрим flame graph, top, list
Пояснение: Промт объясняет, как читать профиль: искать функции с высоким flat/cum, оптимизировать аллокации.
9. Оптимизация аллокаций
Задача: Уменьшить нагрузку на GC за счёт переиспользования памяти.
Промт:
Как использовать sync.Pool для снижения аллокаций в Go? Приведи пример с буферами для JSON-сериализации. Замерь выигрыш.
Пример результата:
var bufPool = sync.Pool{
New: func() interface{} { return new(bytes.Buffer) },
}
func encode(v interface{}) []byte {
buf := bufPool.Get().(*bytes.Buffer)
defer bufPool.Put(buf)
buf.Reset()
json.NewEncoder(buf).Encode(v)
return buf.Bytes()
}
Пояснение: sync.Pool — простой способ снизить давление на GC. Промт показывает реальный кейс.
10. Настройка GODEBUG для диагностики
Задача: Получить детальную информацию о работе планировщика и GC.
Промт:
Какие переменные GODEBUG полезны для отладки высоконагруженных Go-сервисов? Приведи примеры с schedtrace, gctrace.
Пример результата:
GODEBUG=schedtrace=1000,gctrace=1 ./myapp
Пояснение: schedtrace выводит состояние планировщика каждую секунду, gctrace — сборку мусора. Помогает выявить проблемы с latency.
11. Бенчмаркинг и профилирование в тестах
Задача: Автоматизировать сбор профилей при бенчмарках.
Промт:
Как запустить бенчмарк в Go с записью CPU и memory профилей? Покажи команды и код.
Пример результата:
func BenchmarkHTTPHandler(b *testing.B) {
for i := 0; i < b.N; i++ {
// вызов хендлера
}
}
// go test -bench=. -cpuprofile=cpu.out -memprofile=mem.out
Пояснение: Позволяет анализировать производительность на ранних этапах. Промт даёт готовый шаблон.
Как использовать эти промты эффективно
Все промты работают лучше, если вы даёте LLM контекст: версию Go, используемые библиотеки, фрагменты кода. Не стесняйтесь уточнять и просить альтернативы. Помните: сгенерированный код нужно проверять, особенно в критичных к производительности местах. Используйте линтеры, тесты и профилирование.
Эти 11 промтов — не догма, а отправная точка. Комбинируйте их, адаптируйте под свои задачи. Если вы хотите глубже погрузиться в конкурентность, gRPC и профилирование, обратите внимание на курс по Go для высоконагруженных систем. Практика с реальными проектами и разбор ошибок — лучший способ стать экспертом.
Источники:
- Официальная документация Go: https://go.dev/doc/
- Пакет errgroup: https://pkg.go.dev/golang.org/x/sync/errgroup
- gRPC Go: https://grpc.io/docs/languages/go/
- OpenTelemetry Go: https://opentelemetry.io/docs/languages/go/
- Профилирование в Go: https://go.dev/blog/pprof
Комментарии