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
}