Go: effettuare richieste HTTP concorrenti

Go: effettuare richieste HTTP concorrenti

Go è un linguaggio di programmazione noto per la sua facilità d'uso nella gestione della concorrenza. Una delle operazioni comuni che spesso richiedono concorrenza è l'invio di richieste HTTP a più endpoint contemporaneamente. In questo articolo, esploreremo come effettuare richieste HTTP concorrenti in Go utilizzando le librerie standard e le goroutine per massimizzare l'efficienza.

Per effettuare richieste HTTP in Go, useremo il pacchetto net/http. Assicurati di importarlo nel tuo file sorgente:


import (
    "fmt"
    "net/http"
)

Go offre le goroutine, che sono leggere e gestite dal runtime. Possiamo utilizzare le goroutine per eseguire richieste HTTP in modo concorrente e sfruttare al meglio le risorse del sistema. Ecco un esempio su come farlo:


package main

import (
    "fmt"
    "net/http"
    "sync"
)

func fetchURL(url string, wg *sync.WaitGroup) {
    defer wg.Done()

    resp, err := http.Get(url)
    if err != nil {
        fmt.Printf("Errore nella richiesta a %s: %v\n", url, err)
        return
    }
    defer resp.Body.Close()

    fmt.Printf("URL: %s, Stato: %s\n", url, resp.Status)
}

func main() {
    urls := []string{
        "https://www.example.com",
        "https://www.example.org",
        "https://www.example.net",
    }

    var wg sync.WaitGroup

    for _, url := range urls {
        wg.Add(1)
        go fetchURL(url, &wg)
    }

    wg.Wait()
}

In questo esempio, creiamo una funzione fetchURL che effettua una richiesta HTTP al URL fornito e stampa il risultato. Usiamo un sync.WaitGroup per attendere che tutte le goroutine abbiano completato le richieste.

È importante gestire gli errori quando si effettuano richieste HTTP concorrenti. Nel codice sopra, abbiamo incluso una semplice gestione degli errori che stampa un messaggio se la richiesta non ha successo. Puoi personalizzare la gestione degli errori in base alle tue esigenze.

In alcuni casi, potresti voler limitare il numero di goroutine in esecuzione contemporaneamente per evitare di sovraccaricare il sistema. Puoi farlo utilizzando un semaforo o un canale per controllare il numero di goroutine attive.


package main

import (
    "fmt"
    "net/http"
    "sync"
)

func fetchURL(url string, wg *sync.WaitGroup, sem chan struct{}) {
    defer func() {
        sem <- struct{}{}
        wg.Done()
    }()

    resp, err := http.Get(url)
    if err != nil {
        fmt.Printf("Errore nella richiesta a %s: %v\n", url, err)
        return
    }
    defer resp.Body.Close()

    fmt.Printf("URL: %s, Stato: %s\n", url, resp.Status)
}

func main() {
    urls := []string{
        "https://www.example.com",
        "https://www.example.org",
        "https://www.example.net",
    }

    var wg sync.WaitGroup
    sem := make(chan struct{}, 5) // Limita il numero di goroutine attive a 5

    for _, url := range urls {
        wg.Add(1)
        sem <- struct{}{} // Acquisisci uno slot del semaforo
        go fetchURL(url, &wg, sem)
    }

    wg.Wait()
    close(sem)
}

In questo esempio, abbiamo creato un canale sem per limitare il numero di goroutine attive a 5. Ogni goroutine acquisisce uno slot del semaforo prima di iniziare a eseguire la richiesta e lo rilascia una volta completata.

Conclusioni

Effettuare richieste HTTP concorrenti in Go è un modo efficace per migliorare le prestazioni delle tue applicazioni. Utilizzando le goroutine e le strutture di sincronizzazione come il sync.WaitGroup o i canali, puoi gestire facilmente numerose richieste contemporaneamente in modo efficiente e sicuro. Assicurati di gestire gli errori in modo appropriato e di adattare il numero di goroutine attive alle tue esigenze specifiche. Con queste tecniche, sarai in grado di sfruttare al meglio il potenziale di concorrenza offerto da Go nelle tue applicazioni web.

Torna su