Go и Rust давно разошлись по разным нишам: первый — язык сетевых сервисов, оркестраторов и всего, что должно быстро масштабироваться горизонтально; второй — язык системного программирования, где цена ошибки с памятью измеряется в CVE. Но в 2026 году у них появилась общая головная боль: LLM пишут на обоих языках синтаксически валидный код, который разваливается на этапе ревью или, что хуже, в проде.
Горутина без контекста отмены, unsafe-блок «чтобы компилятор замолчал», Arc<Mutex<T>> там, где хватило бы RwLock, и каналы, которые никто не закрывает. Это не ошибки новичков — это типовые артефакты промтов вида «напиши мне микросервис на Go». Проблема не в модели, а в постановке задачи: LLM отлично решает локальные задачи, если вы даёте ей контекст, ограничения и критерии проверки.
Ниже — 12 промтов, которые я собрал и откалибровал на реальных проектах: от генерации идиоматичных горутин до борьбы с borrow checker в async-коде. Каждый промт — это не «магическая фраза», а структура: роль, контекст, ограничения, формат вывода. Разбил их по трём уровням — базовые, продвинутые, экспертные.
Базовые промты: чтобы код компилировался и не стыдно было показать на ревью
1. Идиоматичный Go: отказ от «Java-стиля»
Задача: LLM часто тащит в Go паттерны из ООП-языков: глубокие иерархии интерфейсов, getters/setters, избыточные абстракции.
Промт:
Ты — senior Go-разработчик, ревьюишь код в стиле Effective Go и Google Go Style Guide.
Перепиши следующий код так, чтобы он был идиоматичным: убери лишние абстракции,
используй маленькие интерфейсы (1–2 метода), верни ошибки явно,
замени исключения на sentinel errors или wrapping через fmt.Errorf с %w.
Покажи diff и объясни каждое изменение в 1 строку.
[ВСТАВИТЬ КОД]
Пример результата: модель убирает интерфейс UserServiceInterface с 6 методами, оставляя UserReader и UserWriter, и заменяет panic на возврат ErrNotFound.
2. Горутины с контекстом и WaitGroup
Задача: сгенерировать параллельную обработку, которая корректно отменяется.
Промт:
Напиши на Go функцию, которая параллельно обрабатывает слайс URL,
ограничивая конкурентность до N воркеров.
Требования:
- использовать context.Context для отмены;
- errgroup.Group из golang.org/x/sync/errgroup;
- при первой ошибке отменять остальные задачи;
- не допускать утечки горутин;
- вернуть агрегированную ошибку.
Добавь тест с t.Parallel() и проверкой отмены через context.WithTimeout.
Пример результата: код с errgroup.WithContext, семафором на канале и тестом, где один URL «зависает», а остальные отменяются по таймауту.
3. Rust: борьба с borrow checker без clone()
Задача: новички и LLM лечат ошибки заимствования через .clone(), убивая производительность.
Промт:
Ты — Rust-эксперт. Следующий код не компилируется из-за borrow checker.
Объясни, почему возникает ошибка (E0502/E0499), и предложи 2–3 решения
БЕЗ использования .clone(), .unwrap() и unsafe.
Приоритет: lifetimes и перестроение владения.
Покажи финальный код и объясни, почему он быстрее исходного.
[ВСТАВИТЬ КОД]
Пример результата: модель предлагает разбить функцию на две с разделением mutable/immutable-заимствований и убрать лишний Vec в пользу &[T].
Продвинутые промты: конкурентность, async и производительность
4. Аудит гонок данных в Go
Задача: найти data race до того, как его найдёт go test -race в CI.
Промт:
Проанализируй код на предмет data race и гонок при работе с map/slice.
Для каждого найденного места:
1) укажи строку и тип гонки (read-write, write-write);
2) объясни сценарий, при котором она проявится;
3) предложи фикс: sync.Mutex, sync.RWMutex, atomic или передача владения через канал.
Не предлагай глобальные локи, если можно локализовать.
В конце — как воспроизвести гонку тестом с -race.
[ВСТАВИТЬ КОД]
5. Tokio: async без блокировок рантайма
Задача: самая частая ошибка в Rust-микросервисах — блокирующие вызовы внутри async.
Промт:
Проверь async-код на Tokio на предмет блокирующих операций в async-контексте
(синхронный I/O, std::sync::Mutex, CPU-heavy циклы).
Для каждой проблемы:
- объясни, почему это блокирует executor;
- предложи замену: tokio::task::spawn_blocking, tokio::sync::Mutex, async-версии библиотек.
Покажи исправленный код и объясни, как измерить улучшение (tokio-console, метрики latency).
Пример результата: модель находит std::fs::read_to_string внутри async fn и заменяет на tokio::fs, а std::sync::Mutex — на tokio::sync::Mutex.
6. Оптимизация аллокаций в hot path
Задача: снизить нагрузку на GC в Go и количество heap-аллокаций в Rust.
Промт:
Оптимизируй hot path функции на [Go/Rust] для снижения аллокаций.
Для Go: используй sync.Pool, предаллокацию слайсов, избегай интерфейсов в горячем цикле.
Для Rust: замени Box/Vec на stack-аллокации где возможно, используй SmallVec, ArrayVec.
Покажи бенчмарк до/после (go test -bench / criterion) и объясни, что именно дало выигрыш.
7. Каналы vs мьютексы: выбор под задачу
Задача: LLM по умолчанию тянет каналы даже там, где нужен простой счётчик.
Промт:
У меня задача: [ОПИСАНИЕ]. Какой примитив синхронизации в Go выбрать:
chan, sync.Mutex, sync.RWMutex, atomic, sync.Map?
Дай дерево решений с критериями (частота записи/чтения, размер данных, паттерн доступа).
Покажи реализацию выбранного варианта и антипример — как делать НЕ надо.
Экспертные промты: безопасность памяти, аудит и архитектура
8. Аудит unsafe в Rust
Задача: в проекте накопились unsafe-блоки, нужно оценить риски.
Промт:
Проведи аудит unsafe-блоков в Rust-коде.
Для каждого:
1) проверь соблюдение инвариантов (aliasing, alignment, initialization);
2) укажи, можно ли заменить на safe-код (bytemuck, zerocopy, safe transmute);
3) если unsafe необходим — напиши SAFETY-комментарий по стандарту Rust API Guidelines.
Оцени риск: low/medium/high, с обоснованием.
Пример результата: модель находит transmute для приведения &[u8] к структуре и заменяет на zerocopy::FromBytes, убирая UB.
9. Fuzz-тесты для парсеров на Go
Задача: входные данные из сети — идеальный кандидат для fuzzing.
Промт:
Сгенерируй fuzz-тест для Go-функции парсинга [ФОРМАТ].
Используй нативный fuzzing (go test -fuzz), добавь seed corpus,
проверь отсутствие паник и OOM на больших входах.
Добавь проверку, что парсер не аллоцирует больше N МБ на вход размером M КБ.
10. Безопасные зависимости: аудит supply chain
Задача: проверить, что новый crate/module не тянет уязвимости.
Промт:
Проанализируй зависимости проекта на [Go/Rust].
Для Rust: используй cargo-audit, cargo-deny, проверь лицензии и дубликаты версий.
Для Go: govulncheck, go mod graph, проверь транзитивные зависимости.
Выведи таблицу: пакет, версия, CVE, критичность, альтернатива.
Предложи план миграции с минимальным риском.
11. Архитектура микросервиса: Go vs Rust — обоснованный выбор
Задача: не «хайп», а инженерное решение.
Промт:
Помоги выбрать язык для микросервиса со следующими требованиями: [ОПИСАНИЕ].
Сравни Go и Rust по критериям:
- latency p99 под нагрузкой;
- потребление памяти на инстанс;
- скорость разработки и найм;
- экосистема (gRPC, observability, БД-драйверы);
- безопасность памяти и стоимость ошибок.
Дай таблицу и финальную рекомендацию с обоснованием, без общих фраз.
12. Метрики и трейсинг конкурентного кода
Задача: понять, что происходит внутри горутин и Tokio-тасков в проде.
Промт:
Добавь observability в конкурентный код на [Go/Rust].
Для Go: pprof (goroutine, mutex, block), expvar, OpenTelemetry-трейсинг.
Для Rust: tokio-console, tracing + tracing-subscriber, metrics crate.
Покажи дашборд-запросы (PromQL) для:
- количество активных горутин/тасков;
- latency каналов;
- contention на мьютексах.
Объясни, какие метрики сигналят о проблеме заранее.
Как использовать эти промты, чтобы не выстрелить себе в ногу
Три правила, которые я вывел на практике. Первое: всегда давайте LLM контекст проекта — версию Go/Rust, используемые библиотеки, стиль команды. Без этого модель генерирует «сферический код в вакууме». Второе: просите объяснять решения, а не только писать код — это превращает промт в мини-ревью. Третье: любой сгенерированный код прогоняйте через go vet, staticcheck, clippy и -race/miri. LLM — это ускоритель, а не замена инженерной дисциплине.
Если хотите копнуть глубже — начните с официальных источников: Effective Go (go.dev/doc/effective_go), Rust API Guidelines (rust-lang.github.io/api-guidelines), Tokio Tutorial (tokio.rs/tokio/tutorial) и Rustonomicon (doc.rust-lang.org/nomicon). Промты выше — это каркас; подставьте свои задачи и калибруйте под команду. Хороший промт, как хороший тест: он не доказывает, что код работает, — он доказывает, что вы понимаете, что именно проверяете.
Комментарии