> Как реализовать HTTP сервер на Go, который выполняет параллельные запросы к нескольким системам и агрегирует ответы в JSON (Go)
Уровень: senior · Роль: backend · Категория: Технические вопросы
Компании: X5Tech
Стек: Go
> Пример ответа
Для реализации HTTP сервера на Go, который выполняет параллельные запросы к нескольким системам и агрегирует ответы в JSON, можно использовать горутины и каналы или sync.WaitGroup. Ниже приведен пример с использованием sync.WaitGroup и context для управления таймаутами.
GOpackage mainimport ("context""encoding/json""fmt""io/ioutil""net/http""sync""time")type AggregatedResponse struct {Results map[string]interface{} `json:"results"`Errors map[string]string `json:"errors,omitempty"`}func fetchURL(ctx context.Context, url string, wg *sync.WaitGroup, results chan<- map[string]interface{}, errors chan<- map[string]string) {defer wg.Done()client := http.Client{Timeout: 5 * time.Second}req, err := http.NewRequestWithContext(ctx, "GET", url, nil)if err != nil {errors <- map[string]string{url: err.Error()}return}resp, err := client.Do(req)if err != nil {errors <- map[string]string{url: err.Error()}return}defer resp.Body.Close()body, err := ioutil.ReadAll(resp.Body)if err != nil {errors <- map[string]string{url: err.Error()}return}var data interface{}if err := json.Unmarshal(body, &data); err != nil {errors <- map[string]string{url: err.Error()}return}results <- map[string]interface{}{url: data}}func aggregateHandler(w http.ResponseWriter, r *http.Request) {// Список URL для параллельных запросов (можно получать из запроса)urls := []string{"https://api.example.com/system1","https://api.example.com/system2","https://api.example.com/system3",}ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)defer cancel()var wg sync.WaitGroupresults := make(chan map[string]interface{}, len(urls))errors := make(chan map[string]string, len(urls))for _, url := range urls {wg.Add(1)go fetchURL(ctx, url, &wg, results, errors)}wg.Wait()close(results)close(errors)aggregated := AggregatedResponse{Results: make(map[string]interface{}),Errors: make(map[string]string),}for res := range results {for k, v := range res {aggregated.Results[k] = v}}for err := range errors {for k, v := range err {aggregated.Errors[k] = v}}w.Header().Set("Content-Type", "application/json")json.NewEncoder(w).Encode(aggregated)}func main() {http.HandleFunc("/aggregate", aggregateHandler)fmt.Println("Server started on :8080")http.ListenAndServe(":8080", nil)}
Ключевые моменты:
- Использование
sync.WaitGroupдля ожидания завершения всех горутин. - Каналы
resultsиerrorsдля сбора данных от каждой системы. - Контекст с таймаутом для предотвращения зависания.
- Агрегация результатов в структуру
AggregatedResponseи сериализация в JSON. - Обработка ошибок на каждом этапе (сетевые, парсинг JSON).
Этот код масштабируется: можно легко добавить новые URL или изменить логику агрегации.
> Похожие задачи по backend
Работали ли вы с JSON-полями или специфическими расширениями PostgreSQL
Приходилось ли работать с форматами XML и JSON для обмена данными?
Есть ли проекты с Node.js
Какие подходы и стратегии кэширования существуют в Node.js для улучшения производительности работы с базами данных
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью