Стандартная библиотека и практический 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 server | handler возвращается после записи ответа | неограниченное тело, отсутствие shutdown |
| HTTP client | caller закрывает Response.Body | новые transport/client на каждый запрос |
| SQL | *sql.DB управляет пулом | defer rows.Close, забытый context |
| I/O и FS | reader/writer передают поток, closer имеет владельца | path traversal, чрезмерная память |
| Crypto | CSPRNG и проверенные примитивы | собственная криптография, секреты в логах |
| Logs/tests | наблюдаемое, детерминированное поведение | строковые логи, flaky-тесты |
Типовые вопросы
- Почему нельзя создавать
http.Clientна каждый запрос?- У client/Transport есть pool keep-alive соединений; повторное создание лишает переиспользования и увеличивает FD, handshakes и latency.
- Кто закрывает
http.Response.Body?- Код, получивший response. Он закрывает body на всех путях; для reuse соединения тело обычно читают до конца либо закрывают, понимая, что соединение может не вернуться в pool.
- Почему
sql.Openне проверяет доступность БД?- Он создаёт handle пула и может не установить соединение. Готовность проверяет
PingContextс ограниченным контекстом.
- Он создаёт handle пула и может не установить соединение. Готовность проверяет
- Когда интерфейс
io.Readerлучше[]byte?- Когда данные можно обработать потоком: это ограничивает память и позволяет композицию (
LimitReader, gzip, hash, copy).
- Когда данные можно обработать потоком: это ограничивает память и позволяет композицию (
- Чем
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 · Тестирование