Промты для Go-разработчика: горутины, gRPC и pprof в микросервисах

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

← Все статьи

Комментарии