Как обрабатывать ошибки при параллельном скачивании частей файла
Что проверяют
Умеете ли вы собрать ошибки из горутин без утечек и дедлоков и остановить остальную работу, когда продолжать бессмысленно. Следом обычно спрашивают про повторы, ограничение параллельности и таймауты.
Как отвечать
Опишите схему целиком. HEAD-запрос даёт размер из Content-Length и поддержку диапазонов через Accept-Ranges: bytes. Файл делится на куски, каждая горутина запрашивает свой с заголовком Range: bytes=start-end и пишет через f.WriteAt по своему смещению: запись в непересекающиеся участки одного *os.File из разных горутин безопасна.
Ошибки удобно собирать через errgroup из golang.org/x/sync:
errgroup.WithContext: контекст отменяется при первой ошибке. Его передают вhttp.NewRequestWithContext, и остальные загрузки обрываются, а не качают впустую;g.SetLimit(n): ограничивает число одновременных горутин, чтобы не открыть сотню соединений к одному серверу;g.Wait(): возвращает первую ненулевую ошибку.
Если нужны все сбои, а не первый, копите их в слайс под мьютексом и объединяйте через errors.Join (есть с Go 1.20).
Что считать ошибкой: http.Get не возвращает error на 404 или 500, статус проверяется руками. На диапазон ожидается 206 Partial Content; если пришёл 200, сервер проигнорировал Range и отдаёт весь файл. Сверяйте число прочитанных байт с длиной куска.
Временные сбои (таймаут, 503, обрыв соединения) повторяйте с экспоненциальной задержкой и лимитом попыток, постоянные (404, 416) сразу возвращайте. После сборки проверьте контрольную сумму, если источник её публикует.
Где спотыкаются
Делают канал ошибок с буфером на один элемент и читают его только после wg.Wait(). При двух ошибках вторая горутина блокируется на отправке, Wait не возвращается, программа висит.
Считают успехом любой ответ без error и вклеивают в файл HTML-страницу с ошибкой сервера.
Не передают контекст в запросы. После первой ошибки остальные горутины продолжают качать гигабайты, которые уже никому не нужны.