Стандартная библиотека и практический Go

Стандартная библиотека покрывает большинство границ типичного Go-сервиса: HTTP, SQL через драйвер, потоковый I/O, файловую систему, криптографию, конфигурацию, журналирование и тестирование. Важен не перечень пакетов, а контракт владения ресурсом, дедлайны, ограничения размера входа и проверяемое поведение при ошибке.

Зачем это на интервью

На E4 обычно просят написать handler, клиент или repository и объяснить, где поставить timeout, кто закрывает Body и как протестировать ошибочный путь. На E5 оценивают эксплуатационную модель: connection pool, cancellation, защиту от перегрузки, структуру логов и безопасную обработку секретов.

Минимум для E4

  • Строить сервер из http.Handler, ServeMux и middleware, ограничивать и закрывать request body.
  • Использовать один настроенный http.Client, контекст на запрос и всегда закрывать Response.Body.
  • Понимать, что *sql.DB — пул, а не одно соединение; задавать пределы и применять QueryContext/ExecContext.
  • Работать с io.Reader/Writer, fs.FS, путями и файлами без чтения неограниченного ввода в память.
  • Отличать хеш от шифрования, применять crypto/rand, структурированный slog и testing/httptest.

Углубление для E5/Senior

Граница сервиса — место для политики: бюджет дедлайна, лимит тела, классификация ошибок, redaction, метрики пула и контракт ретраев. Измеряйте последствия: очереди на соединение, p99, число открытых FD, объём логов и долю отменённых операций. Настройки должны иметь документированные безопасные значения по умолчанию и валидироваться до старта serving.

Ключевые понятия

ГраницаБазовый контрактГлавный риск
HTTP serverhandler возвращается после записи ответанеограниченное тело, отсутствие shutdown
HTTP clientcaller закрывает Response.Bodyновые transport/client на каждый запрос
SQL*sql.DB управляет пуломdefer rows.Close, забытый context
I/O и FSreader/writer передают поток, closer имеет владельцаpath traversal, чрезмерная память
CryptoCSPRNG и проверенные примитивысобственная криптография, секреты в логах
Logs/testsнаблюдаемое, детерминированное поведениестроковые логи, flaky-тесты

Типовые вопросы

  1. Почему нельзя создавать http.Client на каждый запрос?
    • У client/Transport есть pool keep-alive соединений; повторное создание лишает переиспользования и увеличивает FD, handshakes и latency.
  2. Кто закрывает http.Response.Body?
    • Код, получивший response. Он закрывает body на всех путях; для reuse соединения тело обычно читают до конца либо закрывают, понимая, что соединение может не вернуться в pool.
  3. Почему sql.Open не проверяет доступность БД?
    • Он создаёт handle пула и может не установить соединение. Готовность проверяет PingContext с ограниченным контекстом.
  4. Когда интерфейс io.Reader лучше []byte?
    • Когда данные можно обработать потоком: это ограничивает память и позволяет композицию (LimitReader, gzip, hash, copy).
  5. Чем slog лучше log.Printf для сервиса?
    • Атрибуты имеют ключи и типы, их можно фильтровать/кодировать в JSON и связывать с request ID без ручного форматирования.

Практика

  • Соберите сервис с маршрутом GET /healthz, JSON endpoint и middleware для request ID. Критерий готовности: handler тестируется через httptest, тело запроса ограничено, а shutdown имеет deadline.
  • Реализуйте клиент к тестовому серверу с Transport, context и проверкой status. Критерий готовности: тест доказывает закрытие body и отмену медленного запроса.
  • Добавьте SQL repository с pool-настройками, затем закройте БД при остановке. Критерий готовности: все запросы используют context, rows.Err() проверяется, лимиты пула заданы явно.
  • Напишите потоковую загрузку файла с SHA-256 и gzip. Критерий готовности: тестирует malformed input и не использует io.ReadAll для неограниченного тела.

Частые ошибки и ловушки

  • Считать timeout одного слоя заменой deadline всей цепочки.
  • Передавать context.Background() из handler в SQL/HTTP вызов и терять отмену клиента.
  • Логировать пароль, bearer token, полный SQL payload или персональные данные.
  • Принимать путь пользователя и склеивать его с каталогом без проверки границы.
  • Писать тесты через time.Sleep вместо синхронизации, context или контролируемого fake.

Связанные темы

Go: язык, runtime и стандартная библиотека · HTTP и Web · PostgreSQL · Observability · Тестирование

Источники