Come effettuare richieste HTTP in Go
L'autore ha selezionato il Diversity in Tech Fund per ricevere una donazione nell'ambito del programma Write for DOnations.
Introduzione
Quando un programma deve comunicare con un altro programma, molti sviluppatori utilizzano HTTP. Uno dei punti di forza di Go è l’ampiezza della sua libreria standard e HTTP non fa eccezione. Il pacchetto Go net/http
non solo supporta la creazione di server HTTP, ma può anche effettuare richieste HTTP come client.
In questo tutorial creerai un programma che effettua diversi tipi di richieste HTTP a un server HTTP. Innanzitutto, effettuerai una richiesta GET
utilizzando il client Go HTTP predefinito. Quindi migliorerai il tuo programma per effettuare una richiesta POST
con un corpo. Infine, personalizzerai la tua richiesta POST
per includere un'intestazione HTTP e aggiungere un timeout che si attiverà se la tua richiesta impiega troppo tempo.
Prerequisiti
Per seguire questo tutorial avrai bisogno di:
- Go versione 1.16 o successiva installata. Per configurarlo, segui il tutorial Come installare Go per il tuo sistema operativo.
- Prova a creare un server HTTP in Go, che puoi trovare nel tutorial Come creare un server HTTP in Go.
- Familiarità con goroutine e canali di lettura. Per ulteriori informazioni, vedere il tutorial Come eseguire più funzioni contemporaneamente in Go.
- Si consiglia di comprendere come viene composta e inviata una richiesta HTTP.
Effettuare una richiesta GET
Il pacchetto Go net/http
prevede diversi modi per utilizzarlo come client. Puoi utilizzare un comune client HTTP globale con funzioni come http.Get
per effettuare rapidamente una richiesta HTTP GET
solo con un URL e un corpo, oppure puoi creare un http.Request
per iniziare a personalizzare alcuni aspetti della singola richiesta. In questa sezione creerai un programma iniziale utilizzando http.Get
per effettuare una richiesta HTTP, quindi lo aggiornerai per utilizzare un http.Request
con il valore HTTP predefinito cliente.
Utilizzo di http.Get
per effettuare una richiesta
Nella prima iterazione del tuo programma, utilizzerai la funzione http.Get
per effettuare una richiesta al server HTTP che esegui nel tuo programma. La funzione http.Get
è utile perché non hai bisogno di alcuna configurazione aggiuntiva nel tuo programma per effettuare una richiesta. Se devi effettuare una singola richiesta rapida, http.Get
potrebbe essere l'opzione migliore.
Per iniziare a creare il tuo programma, avrai bisogno di una directory in cui conservare la directory del programma. In questo tutorial utilizzerai una directory denominata projects
.
Innanzitutto, crea la directory projects
e raggiungila:
mkdir projects
cd projects
Successivamente, crea la directory per il tuo progetto e raggiungila. In questo caso, utilizza la directory httpclient
:
mkdir httpclient
cd httpclient
All'interno della directory httpclient
, utilizza nano
, o il tuo editor preferito, per aprire il file main.go
:
nano main.go
Nel file main.go
, inizia aggiungendo queste righe:
package main
import (
"errors"
"fmt"
"net/http"
"os"
"time"
)
const serverPort = 3333
Aggiungi il nome del pacchetto
main
in modo che il tuo programma sia compilato come un programma che puoi eseguire, quindi includi un'istruzione import
con i vari pacchetti utilizzerai in questo programma. Successivamente, crei un const
chiamato serverPort
con il valore 3333
, che utilizzerai come porta su cui è in ascolto il tuo server HTTP e la porta a cui si connetterà il tuo client HTTP.
Successivamente, crea una funzione main
nel file main.go
e imposta una goroutine per avviare un server HTTP:
...
func main() {
go func() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Printf("server: %s /\n", r.Method)
})
server := http.Server{
Addr: fmt.Sprintf(":%d", serverPort),
Handler: mux,
}
if err := server.ListenAndServe(); err != nil {
if !errors.Is(err, http.ErrServerClosed) {
fmt.Printf("error running http server: %s\n", err)
}
}
}()
time.Sleep(100 * time.Millisecond)
Il tuo server HTTP è configurato per utilizzare fmt.Printf
per stampare informazioni sulle richieste in entrata ogni volta che viene richiesto il percorso root /
. È inoltre impostato per l'ascolto su serverPort
. Infine, una volta avviata la goroutine del server, il tuo programma utilizza time.Sleep
per un breve periodo di tempo. Questo tempo di sospensione concede al server HTTP il tempo necessario per avviarsi e iniziare a fornire risposte alla richiesta che farai successivamente.
Ora, sempre nella funzione main
, imposta l'URL della richiesta utilizzando fmt.Sprintf
per combinare il nome host http://localhost
con il serverPort
valore su cui è in ascolto il server. Quindi, utilizza http.Get
per effettuare una richiesta a quell'URL, come mostrato di seguito:
...
requestURL := fmt.Sprintf("http://localhost:%d", serverPort)
res, err := http.Get(requestURL)
if err != nil {
fmt.Printf("error making http request: %s\n", err)
os.Exit(1)
}
fmt.Printf("client: got response!\n")
fmt.Printf("client: status code: %d\n", res.StatusCode)
}
Quando viene chiamata la funzione http.Get
, Go effettuerà una richiesta HTTP utilizzando il client HTTP predefinito all'URL fornito, quindi restituirà un http.Response
o un errore
se la richiesta fallisce. Se la richiesta fallisce, stamperà l'errore e poi uscirà dal programma utilizzando os.Exit
con un codice di errore 1
. Se la richiesta ha esito positivo, il tuo programma stamperà la risposta ricevuta e il codice di stato HTTP ricevuto.
Salva e chiudi il file quando hai finito.
Per eseguire il tuo programma, usa il comando go run
e forniscigli il file main.go
:
go run main.go
Vedrai il seguente output:
server: GET /
client: got response!
client: status code: 200
Sulla prima riga di output, il server stampa che ha ricevuto una richiesta GET
dal tuo client per il percorso /
. Quindi, le due righe seguenti dicono che il client ha ricevuto una risposta dal server e che il codice di stato della risposta era 200
.
La funzione http.Get
è utile per richieste HTTP veloci come quella che hai fatto in questa sezione. Tuttavia, http.Request
fornisce una gamma più ampia di opzioni per personalizzare la tua richiesta.
Utilizzo di http.Request
per effettuare una richiesta
A differenza di http.Get
, la funzione http.Request
fornisce un maggiore controllo sulla richiesta, oltre al semplice metodo HTTP e all'URL richiesto. Non utilizzerai ancora funzionalità aggiuntive, ma utilizzando una http.Request
adesso, potrai aggiungere tali personalizzazioni più avanti in questo tutorial.
Nel tuo codice, il primo aggiornamento consiste nel modificare il gestore del server HTTP per restituire una risposta di dati JSON falsa utilizzando fmt.Fprintf
. Se si trattasse di un server HTTP completo, questi dati verrebbero generati utilizzando il pacchetto encoding/json
di Go. Se desideri saperne di più sull'utilizzo di JSON in Go, è disponibile il nostro tutorial Come utilizzare JSON in Go. Inoltre, dovrai includere anche il pacchetto io
come importazione da utilizzare più avanti in questo aggiornamento.
Ora apri nuovamente il tuo file main.go
e aggiorna il tuo programma per iniziare a utilizzare una http.Request
come mostrato di seguito:
package main
import (
...
"io"
...
)
...
func main() {
...
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Printf("server: %s /\n", r.Method)
fmt.Fprintf(w, `{"message": "hello!"}`)
})
...
Ora aggiorna il tuo codice di richiesta HTTP in modo che invece di utilizzare http.Get
per effettuare una richiesta al server, utilizzi http.NewRequest
e http.DefaultClient< Metodo
:Do
di
...
requestURL := fmt.Sprintf("http://localhost:%d", serverPort)
req, err := http.NewRequest(http.MethodGet, requestURL, nil)
if err != nil {
fmt.Printf("client: could not create request: %s\n", err)
os.Exit(1)
}
res, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Printf("client: error making http request: %s\n", err)
os.Exit(1)
}
fmt.Printf("client: got response!\n")
fmt.Printf("client: status code: %d\n", res.StatusCode)
resBody, err := io.ReadAll(res.Body)
if err != nil {
fmt.Printf("client: could not read response body: %s\n", err)
os.Exit(1)
}
fmt.Printf("client: response body: %s\n", resBody)
}
In questo aggiornamento, utilizzi la funzione http.NewRequest
per generare un valore http.Request
o gestire l'errore se non è possibile creare il valore. A differenza della funzione http.Get
, però, la funzione http.NewRequest
non invia immediatamente una richiesta HTTP al server. Poiché la richiesta non viene inviata immediatamente, puoi apportare le modifiche che desideri alla richiesta prima che venga inviata.
Una volta creato e configurato http.Request
, utilizza il metodo Do
di http.DefaultClient
per inviare la richiesta al server. Il valore http.DefaultClient
è il client HTTP predefinito di Go, lo stesso che hai utilizzato con http.Get
. Questa volta, però, lo usi direttamente per dirgli di inviare la tua http.Request
. Il metodo Do
del client HTTP restituisce gli stessi valori ricevuti dalla funzione http.Get
in modo che tu possa gestire la risposta nello stesso modo.
Dopo aver stampato i risultati della richiesta, puoi utilizzare la funzione io.ReadAll
per leggere il Body
della risposta HTTP. Il Body
è un valore io.ReadCloser
, una combinazione di io.Reader
e io.Closer
, che significa puoi leggere i dati del corpo utilizzando qualsiasi cosa che possa leggere da un valore io.Reader
. La funzione io.ReadAll
è utile perché legge da un io.Reader
finché non arriva alla fine dei dati o incontra un errore
. Quindi restituirà i dati come valore []byte
che puoi stampare utilizzando fmt.Printf
o il valore error
che ha incontrato.
Per eseguire il programma aggiornato, salva le modifiche e utilizza il comando go run
:
go run main.go
Questa volta, il tuo output dovrebbe essere molto simile a prima, ma con un'aggiunta:
server: GET /
client: got response!
client: status code: 200
client: response body: {"message": "hello!"}
Nella prima riga, vedi che il server sta ancora ricevendo una richiesta GET
al percorso /
. Anche il client riceve una risposta 200
dal server, ma legge e stampa anche il corpo
della risposta del server. In un programma più complesso, potresti quindi prendere il valore {"message": "hello!"}
che hai ricevuto come corpo dal server ed elaborarlo come JSON utilizzando encoding/json pacchetto
.
In questa sezione hai creato un programma con un server HTTP al quale hai effettuato richieste HTTP in vari modi. Innanzitutto, hai utilizzato la funzione http.Get
per effettuare una richiesta GET
al server utilizzando solo l'URL del server. Quindi, hai aggiornato il tuo programma per utilizzare http.NewRequest
per creare un valore http.Request
. Una volta creato, hai utilizzato il metodo Do
del client HTTP predefinito di Go, http.DefaultClient
, per effettuare la richiesta e stampare il http.Response
Corpo
all'output.
Tuttavia, il protocollo HTTP utilizza più che semplici richieste GET
per comunicare tra programmi. Una richiesta GET
è utile quando desideri ricevere informazioni dall'altro programma, ma un altro metodo HTTP, il metodo POST
, può essere utilizzato quando desideri inviare informazioni dal tuo programma al server.
Invio di una richiesta POST
In un'API REST, una richiesta GET
viene utilizzata solo per recuperare informazioni dal server, quindi affinché il tuo programma possa partecipare pienamente a un'API REST, deve anche supportare l'invio di POST richieste. Una richiesta
, in cui il client invia i dati al server nel corpo della richiesta.POST
è quasi l'inverso di una richiesta GET
In questa sezione, aggiornerai il tuo programma per inviare la tua richiesta come richiesta POST
invece che come richiesta GET
. La tua richiesta POST
includerà un corpo della richiesta e aggiornerai il tuo server per stampare ulteriori informazioni sulle richieste che stai effettuando dal client.
Per iniziare a eseguire questi aggiornamenti, apri il file main.go
e aggiungi alcuni nuovi pacchetti che utilizzerai all'istruzione import
:
...
import (
"bytes"
"errors"
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
...
Quindi, aggiorna la funzione del gestore del server per stampare varie informazioni sulla richiesta in arrivo, come i valori della stringa di query, i valori dell'intestazione e il corpo della richiesta:
...
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Printf("server: %s /\n", r.Method)
fmt.Printf("server: query id: %s\n", r.URL.Query().Get("id"))
fmt.Printf("server: content-type: %s\n", r.Header.Get("content-type"))
fmt.Printf("server: headers:\n")
for headerName, headerValue := range r.Header {
fmt.Printf("\t%s = %s\n", headerName, strings.Join(headerValue, ", "))
}
reqBody, err := io.ReadAll(r.Body)
if err != nil {
fmt.Printf("server: could not read request body: %s\n", err)
}
fmt.Printf("server: request body: %s\n", reqBody)
fmt.Fprintf(w, `{"message": "hello!"}`)
})
...
In questo aggiornamento al gestore delle richieste HTTP del server, aggiungi alcune istruzioni fmt.Printf
più utili per visualizzare informazioni sulla richiesta in arrivo. Utilizzi r.URL.Query().Get
per ottenere un valore di stringa di query denominato id
e r.Header.Get
per ottenere il valore di un'intestazione denominata content-type
. Puoi anche utilizzare un ciclo for
con r.Header
per stampare il nome e il valore di ogni intestazione HTTP ricevuta dal server. Queste informazioni possono essere utili per la risoluzione dei problemi se il tuo client o server non funziona come previsto. Infine, hai utilizzato anche la funzione io.ReadAll
per leggere il corpo della richiesta HTTP in r.Body
.
Dopo aver aggiornato la funzione del gestore del server, aggiorna il codice di richiesta della funzione main
in modo che invii una richiesta POST
con un corpo della richiesta:
...
time.Sleep(100 * time.Millisecond)
jsonBody := []byte(`{"client_message": "hello, server!"}`)
bodyReader := bytes.NewReader(jsonBody)
requestURL := fmt.Sprintf("http://localhost:%d?id=1234", serverPort)
req, err := http.NewRequest(http.MethodPost, requestURL, bodyReader)
...
Nell'aggiornamento alla richiesta della funzione main
, uno dei nuovi valori che stai definendo è il valore jsonBody
. In questo esempio, il valore è rappresentato come []byte
anziché come string
standard perché se utilizzi il pacchetto encoding/json
per codificare JSON, ti restituirà un []byte
invece di una string
.
Il valore successivo, bodyReader
, è un bytes.Reader
che racchiude i dati jsonBody
. Un corpo http.Request
richiede che il valore sia un io.Reader
e il []byte
di jsonBody
value non implementa io.Reader
, quindi non potresti utilizzarlo da solo come corpo della richiesta. Il valore bytes.Reader
esiste per fornire l'interfaccia io.Reader
, quindi puoi utilizzare il valore jsonBody
come corpo della richiesta.
Anche il valore requestURL
viene aggiornato per includere un valore della stringa di query id=1234
, principalmente per mostrare come un valore di stringa di query può essere incluso anche nell'URL della richiesta insieme ad altri standard Componenti URL.
Infine, la chiamata alla funzione http.NewRequest
viene aggiornata per utilizzare un metodo POST
con http.MethodPost
e il corpo della richiesta viene incluso aggiornando il ultimo parametro da un corpo nil
a bodyReader
, i dati JSON io.Reader
.
Dopo aver salvato le modifiche, puoi utilizzare go run
per eseguire il programma:
go run main.go
L'output sarà più lungo di prima a causa degli aggiornamenti al server per mostrare informazioni aggiuntive:
server: POST /
server: query id: 1234
server: content-type:
server: headers:
Accept-Encoding = gzip
User-Agent = Go-http-client/1.1
Content-Length = 36
server: request body: {"client_message": "hello, server!"}
client: got response!
client: status code: 200
client: response body: {"message": "hello!"}
La prima riga dal server mostra che la tua richiesta ora arriva come richiesta POST
al percorso /
. La seconda riga mostra il valore 1234
del valore della stringa di query id
che hai aggiunto all'URL della richiesta. La terza riga mostra il valore dell'intestazione Content-Type
inviata dal client, che risulta essere vuota in questa richiesta.
La quarta riga potrebbe essere leggermente diversa dall'output che vedi sopra. In Go, l'ordine di un valore map
non è garantito quando si esegue un'iterazione su di essi utilizzando range
, quindi le intestazioni di r.Headers
potrebbero essere stampate fuori in un ordine diverso. A seconda della versione Go che stai utilizzando, potresti anche vedere una versione User-Agent
diversa da quella sopra.
Infine, l'ultima modifica nell'output è che il server mostra il corpo della richiesta ricevuta dal client. Il server potrebbe quindi utilizzare il pacchetto encoding/json
per analizzare i dati JSON inviati dal client e formulare una risposta.
In questa sezione, hai aggiornato il tuo programma per inviare una richiesta HTTP POST
invece di una richiesta GET
. Hai anche aggiornato il tuo programma per inviare un corpo della richiesta con i dati []byte
letti da un bytes.Reader
. Infine, hai aggiornato la funzione del gestore del server per stampare più informazioni sulla richiesta effettuata dal tuo client HTTP.
Tipicamente in una richiesta HTTP, il client o il server comunicano all'altro il tipo di contenuto che sta inviando nel corpo. Come hai visto nell'ultimo output, tuttavia, la tua richiesta HTTP non includeva un'intestazione Content-Type
per indicare al server come interpretare i dati del corpo. Nella sezione successiva, apporterai alcuni aggiornamenti per personalizzare la tua richiesta HTTP, inclusa l'impostazione di un'intestazione Content-Type
per far conoscere al server il tipo di dati che stai inviando.
Personalizzazione di una richiesta HTTP
Nel corso del tempo, le richieste e le risposte HTTP sono state utilizzate per inviare una maggiore varietà di dati tra client e server. Ad un certo punto, i client HTTP potrebbero presupporre che i dati che ricevono da un server HTTP siano HTML e hanno buone probabilità che siano corretti. Ora, però, potrebbero essere HTML, JSON, musica, video o qualsiasi altro tipo di dati. Per fornire maggiori informazioni sui dati inviati tramite HTTP, il protocollo include intestazioni HTTP e una di queste intestazioni importanti è l'intestazione Content-Type
. Questa intestazione indica al server (o al client, a seconda della direzione dei dati) come interpretare i dati che sta ricevendo.
In questa sezione aggiornerai il tuo programma per impostare l'intestazione Content-Type
sulla tua richiesta HTTP in modo che il server sappia che sta ricevendo dati JSON. Aggiornerai anche il tuo programma per utilizzare un client HTTP diverso dal http.DefaultClient
predefinito di Go in modo da poter personalizzare il modo in cui viene inviata la richiesta.
Per effettuare questi aggiornamenti, apri nuovamente il file main.go
e aggiorna la funzione main
in questo modo:
...
req, err := http.NewRequest(http.MethodPost, requestURL, bodyReader)
if err != nil {
fmt.Printf("client: could not create request: %s\n", err)
os.Exit(1)
}
req.Header.Set("Content-Type", "application/json")
client := http.Client{
Timeout: 30 * time.Second,
}
res, err := client.Do(req)
if err != nil {
fmt.Printf("client: error making http request: %s\n", err)
os.Exit(1)
}
...
In questo aggiornamento, accedi alle intestazioni http.Request
utilizzando req.Header
, quindi imposti il valore dell'intestazione Content-Type
nell'intestazione richiesta a application/json
. Il tipo di media application/json
è definito nell'elenco dei tipi di media come tipo di media per JSON. In questo modo, quando il server riceve la tua richiesta, sa interpretare il corpo come JSON e non, ad esempio, XML.
Il prossimo aggiornamento consiste nel creare la tua istanza http.Client
nella variabile client
. In questo client, imposti il valore Timeout
su 30 secondi. Questo è importante perché dice che qualsiasi richiesta fatta al cliente si arrenderà e smetterà di provare a ricevere una risposta dopo 30 secondi. Il http.DefaultClient
predefinito di Go non specifica un timeout, quindi se effettui una richiesta utilizzando quel client, aspetterà finché non riceve una risposta, viene disconnesso dal server o il tuo programma termina. Se hai molte richieste in attesa di risposta, potresti utilizzare un gran numero di risorse sul tuo computer. L'impostazione di un valore Timeout
limita il tempo di attesa di una richiesta entro l'orario definito.
Infine, hai aggiornato la tua richiesta per utilizzare il metodo Do
della tua variabile client
. Non è necessario apportare altre modifiche qui perché hai sempre chiamato Do
su un valore http.Client
. Il client HTTP predefinito di Go, http.DefaultClient
, è semplicemente un http.Client
creato per impostazione predefinita. Quindi, quando hai chiamato http.Get
, la funzione stava chiamando il metodo Do
per te e quando hai aggiornato la tua richiesta per utilizzare http.DefaultClient
, stavi utilizzando direttamente quel http.Client
. L'unica differenza ora è che hai creato il valore http.Client
che stai utilizzando questa volta.
Ora salva il file ed esegui il programma utilizzando go run
:
go run main.go
L'output dovrebbe essere molto simile all'output precedente ma con maggiori informazioni sul tipo di contenuto:
server: POST /
server: query id: 1234
server: content-type: application/json
server: headers:
Accept-Encoding = gzip
User-Agent = Go-http-client/1.1
Content-Length = 36
Content-Type = application/json
server: request body: {"client_message": "hello, server!"}
client: got response!
client: status code: 200
client: response body: {"message": "hello!"}
Vedrai che c'è un valore dal server per content-type
e c'è un'intestazione Content-Type
inviata dal client. In questo modo potresti avere lo stesso percorso di richiesta HTTP che serve contemporaneamente sia un'API JSON che un'API XML. Specificando il tipo di contenuto della richiesta, il server e il client possono interpretare i dati in modo diverso.
Tuttavia, questo esempio non attiva il timeout del client configurato. Per vedere cosa succede quando una richiesta impiega troppo tempo e viene attivato il timeout, apri il file main.go
e aggiungi una chiamata alla funzione time.Sleep
alla funzione del gestore del server HTTP . Quindi, fai in modo che time.Sleep
duri più a lungo del timeout specificato. In questo caso, lo imposterai per 35 secondi:
...
func main() {
go func() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
...
fmt.Fprintf(w, `{"message": "hello!"}`)
time.Sleep(35 * time.Second)
})
...
}()
...
}
Ora salva le modifiche ed esegui il programma utilizzando go run
:
go run main.go
Quando lo esegui questa volta, ci vorrà più tempo per uscire rispetto a prima perché non uscirà fino al termine della richiesta HTTP. Dato che hai aggiunto time.Sleep(35 * time.Second)
, la richiesta HTTP non verrà completata finché non verrà raggiunto il timeout di 30 secondi:
server: POST /
server: query id: 1234
server: content-type: application/json
server: headers:
Content-Type = application/json
Accept-Encoding = gzip
User-Agent = Go-http-client/1.1
Content-Length = 36
server: request body: {"client_message": "hello, server!"}
client: error making http request: Post "http://localhost:3333?id=1234": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
exit status 1
Nell'output di questo programma, vedi che il server ha ricevuto la richiesta e l'ha elaborata, ma quando ha raggiunto la fine della funzione del gestore HTTP dove si trova la chiamata alla funzione time.Sleep
, ha iniziato a dormire per 35 secondi. Allo stesso tempo, il timeout della tua richiesta HTTP scorre e raggiunge il limite di 30 secondi prima che la richiesta HTTP termini. Ciò fa sì che la chiamata al metodo client.Do
fallisca con un errore scadenza contesto superata
perché la scadenza di 30 secondi della richiesta è trascorsa. Quindi, il programma termina con un codice di stato di errore 1
utilizzando os.Exit(1)
.
In questa sezione hai aggiornato il tuo programma per personalizzare una richiesta HTTP aggiungendovi un'intestazione Content-Type
. Hai anche aggiornato il tuo programma per creare un nuovo http.Client
con un timeout di 30 secondi e poi hai utilizzato quel client per effettuare una richiesta HTTP. Hai anche testato il timeout di 30 secondi aggiungendo un time.Sleep
al tuo gestore di richieste HTTP. Infine, hai anche visto perché è importante utilizzare i tuoi valori http.Client
con i timeout impostati se vuoi evitare che molte richieste restino potenzialmente inattive per sempre.
Conclusione
In questo tutorial, hai creato un nuovo programma con un server HTTP e hai utilizzato il pacchetto net/http
di Go per effettuare richieste HTTP a quel server. Innanzitutto, hai utilizzato la funzione http.Get
per effettuare una richiesta GET
al server con il client HTTP predefinito di Go. Quindi, hai utilizzato http.NewRequest
con il metodo Do
di http.DefaultClient
per effettuare una richiesta GET
. Successivamente, hai aggiornato la tua richiesta per renderla una richiesta POST
con un corpo utilizzando bytes.NewReader
. Infine, hai utilizzato il metodo Set
sul campo Header
di http.Request
per impostare il Content-Type
di una richiesta > e imposta un timeout di 30 secondi sulla durata di una richiesta creando il tuo client HTTP invece di utilizzare il client predefinito di Go.
Il pacchetto net/http
include molto più della semplice funzionalità utilizzata in questo tutorial. Include anche una funzione http.Post
che può essere utilizzata per effettuare una richiesta POST
, simile alla funzione http.Get
. Il pacchetto supporta anche il salvataggio e il recupero dei cookie, tra le altre funzionalità.
Questo tutorial fa anche parte della serie DigitalOcean How to Code in Go. La serie copre una serie di argomenti su Go, dall'installazione di Go per la prima volta a come utilizzare la lingua stessa.