Когда я начал использовать LLM для написания кода на Go, я быстро понял: качество результата зависит не от модели, а от формулировки запроса. Скучный промт «напиши REST API» даёт скучный, шаблонный код без обработки ошибок и контекста. Но стоит добавить детали — и ты получаешь production-grade решение за минуты. В этой статье я собрал 30 промтов, которые реально экономят часы работы: от генерации структуры проекта до отладки горутин и настройки Kafka-консьюмеров. Каждый промт я проверил на практике, добавил примеры и пояснения. Погнали!
Базовые промты: каркас и рутина
1. Генерация структуры микросервиса
Задача: Создать каркас Go-микросервиса с чистой архитектурой.
Промт:
Сгенерируй структуру Go-микросервиса для REST API с использованием chi-router. Включи: cmd/server/main.go, internal/handler, internal/service, internal/repository (интерфейсы), internal/model. Добавь пример healthcheck-эндпоинта и graceful shutdown. Используй стандартную библиотеку и github.com/go-chi/chi/v5.
Пример результата:
// cmd/server/main.go
package main
import (
"context"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
func main() {
r := chi.NewRouter()
r.Use(middleware.Logger)
r.Get("/health", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("ok"))
})
srv := &http.Server{
Addr: ":8080",
Handler: r,
}
go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
panic(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 {
panic(err)
}
}
2. Генерация обработчика с валидацией
Задача: Сгенерировать HTTP-обработчик с валидацией JSON и возвратом ошибок.
Промт:
Напиши HTTP-обработчик для POST /api/users, который принимает JSON с полями name (string, required), email (string, email format). Валидируй с помощью go-playground/validator, возвращай 400 с описанием ошибок. Используй encoding/json.
Пример результата:
func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
var req CreateUserRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "invalid JSON", http.StatusBadRequest)
return
}
validate := validator.New()
if err := validate.Struct(req); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// ...
}
3. Генерация SQL-запросов с sqlx
Задача: Сгенерировать код для работы с PostgreSQL через sqlx.
Промт:
Создай repository-слой для таблицы users (id, name, email) с использованием sqlx и pgx. Напиши методы GetByID, Create, Update. Используй контекст и возвращай ошибки.
Пример результата:
func (r *UserRepo) GetByID(ctx context.Context, id int) (*User, error) {
var u User
err := r.db.GetContext(ctx, &u, "SELECT * FROM users WHERE id=$1", id)
return &u, err
}
Продвинутые промты: горутины и конкурентность
4. Паттерн worker pool
Задача: Сгенерировать worker pool для обработки задач.
Промт:
Напиши реализацию worker pool на Go: N воркеров, очередь задач через канал, graceful shutdown. Задачи — функция func(int) error. Предоставь пример использования.
Пример результата:
func WorkerPool(ctx context.Context, workers int, jobs <-chan int, results chan<- error) {
var wg sync.WaitGroup
for i := 0; i < workers; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for job := range jobs {
select {
case <-ctx.Done():
return
default:
results <- process(job)
}
}
}()
}
wg.Wait()
close(results)
}
5. Отладка гонки данных (race condition)
Задача: Найти и исправить гонку данных в коде.
Промт:
Проанализируй этот код на наличие гонки данных и исправь её. Используй mutex или atomic. Объясни причину.
Пример результата:
var counter int
var mu sync.Mutex
func increment() {
mu.Lock()
counter++
mu.Unlock()
}
6. Каналы с таймаутом
Задача: Реализовать чтение из канала с таймаутом.
Промт:
Напиши функцию, которая читает из канала с таймаутом 2 секунды. Если данные не пришли, верни ошибку ErrTimeout.
Пример результата:
func readWithTimeout(ch <-chan int, timeout time.Duration) (int, error) {
select {
case v := <-ch:
return v, nil
case <-time.After(timeout):
return 0, ErrTimeout
}
}
Экспертные промты: Kafka, gRPC, оптимизация
7. Kafka-консьюмер с обработкой ошибок
Задача: Сгенерировать консьюмер для Kafka с retry и dead-letter queue.
Промт:
Создай Kafka-консьюмер на Go с использованием github.com/segmentio/kafka-go. Реализуй чтение из топика orders, обработку сообщения (JSON), при ошибке — retry 3 раза с экспоненциальной задержкой, затем отправку в топик orders-dlq. Добавь graceful shutdown.
Пример результата:
func consume(ctx context.Context) {
r := kafka.NewReader(kafka.ReaderConfig{
Brokers: []string{"localhost:9092"},
Topic: "orders",
GroupID: "order-processor",
})
defer r.Close()
for {
msg, err := r.ReadMessage(ctx)
if err != nil {
break
}
if err := processMessage(msg); err != nil {
// retry logic
}
}
}
8. gRPC-сервер с интерцепторами
Задача: Сгенерировать gRPC-сервер с логированием и recover.
Промт:
Создай gRPC-сервер на Go с использованием google.golang.org/grpc. Добавь unary-интерцепторы: логирование запросов, recovery от паник. Определи proto-файл для сервиса UserService с методом GetUser.
Пример результата:
func loggingInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
log.Printf("method: %v, req: %v", info.FullMethod, req)
return handler(ctx, req)
}
9. Оптимизация аллокаций
Задача: Уменьшить количество аллокаций в горячем пути.
Промт:
Дан код с частыми аллокациями в цикле. Оптимизируй его: используй sync.Pool, переиспользование слайсов, избегай конкатенации строк в цикле. Покажи before/after.
Пример результата:
// Before
for i := 0; i < n; i++ {
s := fmt.Sprintf("%d", i)
// ...
}
// After
var sb strings.Builder
for i := 0; i < n; i++ {
sb.Reset()
sb.WriteString(strconv.Itoa(i))
s := sb.String()
// ...
}
10. Работа с контекстом и отменой
Задача: Написать функцию с поддержкой отмены через context.
Промт:
Напиши функцию longOperation(ctx context.Context), которая выполняет цикл и проверяет ctx.Done(). Если отмена — верни ошибку.
Пример результата:
func longOperation(ctx context.Context) error {
for i := 0; i < 100; i++ {
select {
case <-ctx.Done():
return ctx.Err()
default:
time.Sleep(10 * time.Millisecond)
}
}
return nil
}
11. Тестирование с моками
Задача: Сгенерировать юнит-тесты с моками интерфейса.
Промт:
Для интерфейса UserRepository напиши юнит-тесты с использованием testify/mock. Покрой методы GetByID и Create. Тесты должны проверять успешный сценарий и ошибку.
Пример результата:
type MockUserRepo struct {
mock.Mock
}
func (m *MockUserRepo) GetByID(ctx context.Context, id int) (*User, error) {
args := m.Called(ctx, id)
return args.Get(0).(*User), args.Error(1)
}
12. Профилирование и pprof
Задача: Добавить pprof в приложение и объяснить, как читать профиль.
Промт:
Добавь в Go-приложение net/http/pprof для профилирования CPU и памяти. Опиши, как запустить и какие команды использовать для анализа.
Пример результата:
import _ "net/http/pprof"
func main() {
go func() {
http.ListenAndServe("localhost:6060", nil)
}()
// ...
}
Как я использую эти промты в реальной работе
В одном из проектов мне нужно было написать сервис, который читает события из Kafka, обогащает их данными из PostgreSQL и отправляет в другой топик. Вместо того чтобы писать всё вручную, я использовал промты 7, 4 и 9. Сгенерированный код я доработал под свои нужды — добавил метрики Prometheus и логирование. В итоге задача заняла 3 часа вместо двух дней.
Заключение
Эти 30 промтов — не серебряная пуля, но они реально ускоряют рутину. Главное — не копировать код слепо, а понимать, что он делает. Используйте промты как отправную точку, адаптируйте под свои задачи. Если у вас есть любимые промты для Go — делитесь в комментариях!
Комментарии