Как программа определяет URL для выполнения запросов по списку
Что проверяют
Умеете ли вы надёжно превращать входные данные в корректные адреса и отправлять по ним запросы стандартными средствами Go. Обычно это часть задачи «обойти список URL», и следом спрашивают про валидацию, таймауты и параллельную обработку.
Как отвечать
Опишите путь адреса от входа до запроса:
- источник: список приходит срезом, файлом (читается построчно через
bufio.Scanner) или из канала от продюсера. Пустые строки и комментарии отбрасываются сразу; - разбор:
url.Parseочень снисходителен. Строкаexample.comразберётся с пустыми схемой и хостом и целиком попадёт в путь. Поэтому после разбора проверяем, чтоu.Schemeравнаhttpилиhttps, аu.Hostне пустой.url.ParseRequestURIстроже, но эту проверку не заменяет; - сборка из частей: базовый адрес плюс путь через
url.JoinPath(есть с Go 1.19) илиResolveReferenceдля относительных ссылок. Параметры черезurl.ValuesиEncode(), который сам экранирует значения; - запрос:
http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)и один общийhttp.Clientс заданнымTimeoutна всю программу, чтобы соединения переиспользовались; - распределение: адреса отправляются в канал, из которого читает фиксированное число воркеров. Так ограничивается параллелизм и нагрузка на чужие серверы.
Из-за одного невалидного адреса программа не должна падать: его логируют с номером строки и идут дальше.
Где спотыкаются
Склеивают URL конкатенацией строк. Пробел, амперсанд или кириллица в параметре ломают запрос, нужны url.Values либо url.QueryEscape и url.PathEscape.
Ожидают, что Encode() сохранит порядок параметров. Он сортирует их по ключу, и page=1&limit=10 превратится в limit=10&page=1. Серверу обычно всё равно, а вот тест со сравнением строк упадёт.
Используют http.Get с клиентом по умолчанию, у которого нет таймаута, и забывают defer resp.Body.Close(). Один зависший хост держит воркер вечно, а незакрытые тела не дают переиспользовать соединения.