Middle+
Εργασία: «Παραλληλική επεξεργασία URL με περιορισμό χρόνου» Γράψτε μια συνάρτηση fetchAll(urls []string, maxParallel int, timeout time.Duration) map[string]string, που: 1. Για κάθε URL πραγματοποιεί ένα αίτημα HTTP GET (μπορεί να χρησιμοποιηθεί το http.Get). 2. Επιστρέφει ένα map[string]string, όπου το κλειδί είναι το URL και η τιμή το σώμα της απάντησης (ως συμβολοσειρά) ή μια κενή συμβολοσειρά σε περίπτωση σφάλματος/timeout. 3. Δεν εκτελούνται περισσότερα από maxParallel αιτήματα ταυτόχρονα. 4. Ο συνολικός χρόνος λειτουργίας της συνάρτησης δεν πρέπει να υπερβαίνει το timeout. Αν λήξει ο χρόνος, όλες οι μη ολοκληρωμένες αιτήσεις διακόπτονται και η συνάρτηση επιστρέφει ό,τι κατάφερε. 5. Χρησιμοποιήστε το context για ακύρωση.
sobes.tech AI
Απάντηση από AI
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) // σημαφόρος για τον περιορισμό του παραλληλισμού
var wg sync.WaitGroup
for _, url := range urls {
select {
case <-ctx.Done():
break
default:
wg.Add(1)
sem <- struct{}{} // κρατάμε μια θέση
go func(u string) {
defer wg.Done()
defer func() { <-sem }() // ελευθερώνουμε τη θέση
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
}