Sobes.tech
Middle+

Tarea: «Procesamiento paralelo de URL con límite de tiempo» Escriba una función fetchAll(urls []string, maxParallel int, timeout time.Duration) map[string]string, que: 1. Para cada URL realiza una solicitud HTTP GET (se puede usar http.Get). 2. Devuelve un map[string]string, donde la clave es la URL, y el valor es el cuerpo de la respuesta (como cadena) o una cadena vacía en caso de error/timeout. 3. No se ejecutan más de maxParallel solicitudes simultáneamente. 4. El tiempo total de ejecución de la función no debe exceder timeout. Si se agota el tiempo, todas las solicitudes no finalizadas se cancelan, y la función devuelve lo que haya podido. 5. Use context para cancelar.

sobes.tech AI

Respuesta de la IA

go package main

import ( "context" "io/ioutil" "net/http" "sync" "time" )

func fetchAll(urls []string, maxParallel int, timeout time.Duration) map[string]string { ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel()

results := make(map[string]string)
var mu sync.Mutex
sem := make(chan struct{}, maxParallel) // semáforo para limitar el paralelismo
var wg sync.WaitGroup

for _, url := range urls {
	select {
	case <-ctx.Done():
		break
	default:
		wg.Add(1)
		sem <- struct{}{} // reservamos un espacio

		go func(u string) {
			defer wg.Done()
			defer func() { <-sem }() // liberamos el espacio

			req, err := http.NewRequestWithContext(ctx, "GET", u, nil)
			if err != nil {
				mu.Lock()
				results[u] = ""
				mu.Unlock()
				return
			}

			resp, err := http.DefaultClient.Do(req)
			if err != nil {
				mu.Lock()
				results[u] = ""
				mu.Unlock()
				return
			}
			defer resp.Body.Close()

			body, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				mu.Lock()
				results[u] = ""
				mu.Unlock()
				return
			}

			mu.Lock()
			results[u] = string(body)
			mu.Unlock()
		}(url)
	}
}

wg.Wait()
return results

}