10 промтов для Go: микросервисы, API и CLI утилиты
Разработка на Go — это работа с производительностью, простотой и параллелизмом. Но даже опытные разработчики тратят часы на шаблонный код: настройку HTTP-роутера, обработку ошибок, генерацию CLI-флагов. Я собрал 10 проверенных промтов, которые ускоряют рутину и помогают сосредоточиться на бизнес-логике. Каждый промт — это готовый шаблон, который можно адаптировать под свой проект.
1. Создание микросервиса с HTTP-сервером и graceful shutdown
Промт: «Напиши на Go микросервис с HTTP-сервером на net/http, graceful shutdown, логированием через log/slog и обработкой ошибок. Используй стандартную библиотеку без фреймворков.»
Пример:
package main
import (
"context"
"log/slog"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"status":"ok"}`))
})
srv := &http.Server{
Addr: ":8080",
Handler: mux,
}
go func() {
slog.Info("Server started on :8080")
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
slog.Error("Server error", "error", err)
os.Exit(1)
}
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
slog.Info("Shutting down...")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
slog.Error("Shutdown error", "error", err)
}
}
Совет: Используй log/slog (Go 1.21+) — он структурированный и совместим с стандартными инструментами.
2. Генерация REST API с валидацией через validator
Промт: «Создай REST API на Go с использованием chi роутера, JSON-эндпоинтами и валидацией через go-playground/validator. Включи обработку ошибок с кодом 400.»
Пример:
package main
import (
"encoding/json"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-playground/validator/v10"
)
type User struct {
Name string `json:"name" validate:"required,min=2,max=50"`
Email string `json:"email" validate:"required,email"`
}
var validate = validator.New()
func createUser(w http.ResponseWriter, r *http.Request) {
var user User
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
http.Error(w, `{"error":"invalid JSON"}`, http.StatusBadRequest)
return
}
if err := validate.Struct(user); err != nil {
http.Error(w, `{"error":"validation failed"}`, http.StatusBadRequest)
return
}
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(user)
}
func main() {
r := chi.NewRouter()
r.Post("/users", createUser)
http.ListenAndServe(":8080", r)
}
Почему это работает: Chi — легковесный роутер, совместимый с net/http. Валидация go-playground/validator — стандарт де-факто (используется в Kubernetes, Docker).
3. CLI-утилита с cobra и viper
Промт: «Создай CLI утилиту на Go с cobra для команд, viper для конфигурации из файла и переменных окружения. Добавь команду 'serve' с флагом --port.»
Пример:
package main
import (
"fmt"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var rootCmd = &cobra.Command{
Use: "myapp",
Short: "My CLI app",
}
var serveCmd = &cobra.Command{
Use: "serve",
Short: "Start server",
Run: func(cmd *cobra.Command, args []string) {
port := viper.GetInt("port")
fmt.Printf("Starting server on :%d\n", port)
},
}
func init() {
serveCmd.Flags().IntP("port", "p", 8080, "Port to listen on")
viper.BindPFlag("port", serveCmd.Flags().Lookup("port"))
rootCmd.AddCommand(serveCmd)
}
func main() {
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
viper.AutomaticEnv()
viper.ReadInConfig()
rootCmd.Execute()
}
Совет: Cobra — стандарт для CLI в Go (используется в Kubernetes, Hugo). Viper автоматически читает YAML/JSON и env.
4. Работа с PostgreSQL через database/sql и sqlx
Промт: «Напиши Go-код для подключения к PostgreSQL через database/sql и sqlx. Выполни SELECT с маппингом в структуру, используя пул соединений.»
Пример:
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/lib/pq"
"github.com/jmoiron/sqlx"
)
type User struct {
ID int `db:"id"`
Name string `db:"name"`
Age int `db:"age"`
}
func main() {
db, err := sqlx.Connect("postgres", "user=postgres dbname=test sslmode=disable")
if err != nil {
log.Fatal(err)
}
defer db.Close()
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(5)
var users []User
err = db.Select(&users, "SELECT id, name, age FROM users WHERE age > $1", 18)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Users: %+v\n", users)
}
Почему это важно: Sqlx минимизирует шаблонный код, а database/sql даёт контроль над пулом.
5. Graceful shutdown с контекстом для фоновых задач
Промт: «Реализуй в Go graceful shutdown для воркера, который обрабатывает задачи из канала. Используй context.WithCancel.»
Пример:
package main
import (
"context"
"fmt"
"os/signal"
"syscall"
"time"
)
func worker(ctx context.Context, jobs <-chan int) {
for {
select {
case job := <-jobs:
fmt.Printf("Processing job %d\n", job)
time.Sleep(100 * time.Millisecond)
case <-ctx.Done():
fmt.Println("Worker shutting down...")
return
}
}
}
func main() {
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer cancel()
jobs := make(chan int, 10)
go worker(ctx, jobs)
for i := 0; i < 5; i++ {
jobs <- i
}
close(jobs)
<-ctx.Done()
fmt.Println("Main stopped")
}
Совет: Используй signal.NotifyContext — это идиоматичный способ в Go 1.16+.
6. Middleware для логирования и метрик
Промт: «Создай middleware для chi-роутера, который логирует метод, путь, статус и время выполнения.»
Пример:
package main
import (
"log/slog"
"net/http"
"time"
)
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
ww := &responseWriter{ResponseWriter: w, statusCode: http.StatusOK}
next.ServeHTTP(ww, r)
slog.Info("Request",
"method", r.Method,
"path", r.URL.Path,
"status", ww.statusCode,
"duration", time.Since(start),
)
})
}
type responseWriter struct {
http.ResponseWriter
statusCode int
}
func (rw *responseWriter) WriteHeader(code int) {
rw.statusCode = code
rw.ResponseWriter.WriteHeader(code)
}
Почему это полезно: Структурированное логирование упрощает отладку в продакшене.
7. Тестирование HTTP-сервера с httptest
Промт: «Напиши unit-тест для HTTP-эндпоинта на Go с использованием httptest.»
Пример:
func TestHealthEndpoint(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "/health", nil)
w := httptest.NewRecorder()
handler(w, req)
resp := w.Result()
body, _ := io.ReadAll(resp.Body)
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Contains(t, string(body), `"status":"ok"`)
}
Совет: Используй testify/assert для читаемых проверок.
8. Работа с JSON: сериализация и десериализация
Промт: «Напиши Go-функцию для парсинга JSON с вложенными объектами и массивами, используя encoding/json.»
Пример:
type Config struct {
Database struct {
Host string `json:"host"`
Port int `json:"port"`
Settings []struct {
Key string `json:"key"`
Value string `json:"value"`
} `json:"settings"`
} `json:"database"`
}
func parseConfig(data []byte) (Config, error) {
var cfg Config
err := json.Unmarshal(data, &cfg)
return cfg, err
}
Почему это стандарт: encoding/json — часть стандартной библиотеки, не требует зависимостей.
9. Работа с файлами и директориями
Промт: «Создай Go-функцию для рекурсивного обхода директории и фильтрации файлов по расширению.»
Пример:
func findFiles(root, ext string) ([]string, error) {
var files []string
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && strings.HasSuffix(info.Name(), ext) {
files = append(files, path)
}
return nil
})
return files, err
}
Совет: Используй filepath.Walk или os.ReadDir для производительности.
10. Параллельные горутины с sync.WaitGroup
Промт: «Напиши на Go функцию, которая запускает 10 горутин, каждая обрабатывает элемент из слайса, и ждёт завершения всех через sync.WaitGroup.»
Пример:
func processItems(items []int) {
var wg sync.WaitGroup
for _, item := range items {
wg.Add(1)
go func(i int) {
defer wg.Done()
fmt.Printf("Processing %d\n", i)
time.Sleep(100 * time.Millisecond)
}(item)
}
wg.Wait()
}
Почему это важно: WaitGroup — простой способ синхронизации горутин без каналов.
Заключение
Эти 10 промтов покрывают 80% задач, с которыми сталкивается Go-разработчик: от создания микросервиса до работы с БД и CLI. Сохрани их в свой набор — они сэкономят часы на рутинном коде. Попробуй адаптировать каждый пример под свой проект, и ты увидишь, как ускоряется разработка.
Комментарии