> Приходилось ли работать с базами данных? (Go)
Уровень: middle · Роль: backend · Категория: Технические вопросы
Компании: Axel Pro, Wildberries, VK
Стек: Go
> Пример ответа
Короткий ответ
Да, работал с реляционными базами данных (PostgreSQL, MySQL) и с Redis как кэшем. В основном использовал SQL через database/sql и pgx, писал миграции, проектировал схемы, оптимизировал запросы через EXPLAIN ANALYZE. Также сталкивался с транзакциями, конкурентным доступом и проблемами блокировок. В Go работал с пулами соединений, контекстами и обработкой ошибок при работе с БД.
Подробное объяснение
В повседневной работе с БД в Go выделяю несколько ключевых аспектов:
- Драйверы и библиотеки: для PostgreSQL чаще использую
pgx(включаяpgxpoolдля пула соединений), для MySQL -go-sql-driver/mysql. Стандартныйdatabase/sql- хорошая абстракция, но при сложных запросах или необходимости в prepared statements удобнее работать с pgx напрямую. - Миграции: использую golang-migrate или goose, храню миграции в репозитории, применяю при деплое.
- Проектирование схемы: нормализация до третьей формы, индексы под частые запросы, внешние ключи для целостности.
- Транзакции: оборачиваю операции в
tx, слежу за commit/rollback, используюdeferдля отката при ошибке. - Конкурентность: пул соединений ограничиваю через
MaxConns, учитываю, что каждая горутина получает отдельное соединение из пула. - Оптимизация: смотрю
EXPLAIN ANALYZE, добавляю индексы, избегаю N+1 запросов, использую JOIN и агрегации на стороне БД.
На практике
Типичный сценарий - REST API с CRUD-операциями. Схема: таблица users с полями id, email, created_at. Для поиска по email добавляю уникальный индекс. При создании пользователя проверяю уникальность через ON CONFLICT DO NOTHING или ловлю ошибку дубликата.
Для списка с пагинацией использую LIMIT/OFFSET или cursor-based пагинацию через WHERE id > $1 ORDER BY id LIMIT $2. Второй вариант предпочтительнее при больших объёмах данных.
При работе с Redis - кэширование часто запрашиваемых данных, инвалидация по ключу, использование TTL. Для атомарных операций - INCR, SETNX для реализации распределённых блокировок.
Пример кода
GOtype User struct {ID int64Email string}func CreateUser(ctx context.Context, pool *pgxpool.Pool, email string) (*User, error) {var user Usererr := pool.QueryRow(ctx, `INSERT INTO users (email)VALUES ($1)ON CONFLICT (email) DO NOTHINGRETURNING id, email`, email).Scan(&user.ID, &user.Email)if errors.Is(err, pgx.ErrNoRows) {return nil, ErrDuplicateEmail}return &user, err}func GetUsers(ctx context.Context, pool *pgxpool.Pool, limit, offset int) ([]User, error) {rows, err := pool.Query(ctx, `SELECT id, email FROM usersORDER BY idLIMIT $1 OFFSET $2`, limit, offset)if err != nil {return nil, err}defer rows.Close()users := make([]User, 0)for rows.Next() {var u Userif err := rows.Scan(&u.ID, &u.Email); err != nil {return nil, err}users = append(users, u)}return users, rows.Err()}
Как отвечать на собеседовании
Начни с конкретики: какие БД использовал, в каких проектах, какой стек. Затем переходи к деталям - как проектировал схему, какие проблемы решал (медленные запросы, блокировки, конкурентный доступ). Обязательно упомяни, как работаешь с пулом соединений и контекстами в Go. Если спрашивают про оптимизацию - расскажи про индексы и EXPLAIN. Не бойся признаться, что не знаешь какую-то специфическую фичу, но покажи, что понимаешь общие принципы.
Что проверяет интервьюер
- Понимание основ SQL: JOIN, GROUP BY, индексы, транзакции.
- Умение работать с database/sql и драйверами в Go.
- Знание пула соединений, контекстов, обработки ошибок.
- Способность проектировать схему под нагрузку.
- Практический опыт оптимизации запросов.
- Понимание trade-off между нормализацией и производительностью.
Типичные ошибки
- Не упоминать про
context.Contextпри работе с БД - это критично для Go. - Говорить только про ORM (например, GORM) без понимания SQL - интервьюер может спросить про конкретный запрос.
- Игнорировать пул соединений и его настройку.
- Не знать разницу между
database/sqlи драйверами. - Забывать про
rows.Close()иrows.Err()после итерации. - Предлагать
SELECT *без необходимости - это плохая практика. - Не упоминать про миграции и управление схемой.
> Похожие задачи по backend
Являются ли мапы в Go потокобезопасными
Какие способы копирования слайса в Go существуют
Что такое сбалансированное дерево
Что такое модель OSI и как она работает
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью