É muito comum que um programa precise se comunicar com outro, seja para uma integração com outros sistemas ou microsserviços internos.
Embora em alguns casos essa comunicação possa ser feita com gRPC, o mais comum é que elas sejam feita através de uma API (Application Programming Interface) REST.
Nesse post vamos ver como fazer requisições (GET, POST e etc..) e tratar sua resposta.
GET
Para começar, vamos importar 3 packages.
io/ioutil
para fazer leitura da resposta;log
para logar os erros;net/http
para executar a requisição.
Com os packages importados, podemos executar nossa requisição e verificar se houve algum erro.
func main() { resp, err := http.Get("https://jsonplaceholder.typicode.com/posts") if err != nil { log.Fatalln(err) } }
Validado se houve algum erro na requisição, vamos fazer a leitura da resposta.
func main() { resp, err := http.Get("https://jsonplaceholder.typicode.com/posts") if err != nil { log.Fatalln(err) } body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatalln(err) } defer resp.Body.Close() }
Como a função ioutil.ReadAll
retorna um array de bytes, nosso próximo passo pode ser converter a variável body
para string e exibir no terminal, ou associar à uma struct e então exibir o resultado no terminal.
Como a string seria muito simples, vamos fazer a segunda opção. Para isso, precisamos importar o package encoding/json
e criar uma struct que chamaremos de Post.
type Post struct { UserID int32 `json:"userId"` ID int32 `json:"id"` Title string `json:"title"` Body string `json:"body"` }
Voltando para nossa função, vamos criar uma variável para armazenar os posts e utilizar a função json.Unmarshal
para popular essa variável como resultado da requisição.
func main() { resp, err := http.Get("https://jsonplaceholder.typicode.com/posts") if err != nil { log.Fatalln(err) } body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatalln(err) } defer resp.Body.Close() var posts []Post err = json.Unmarshal(body, &posts) if err != nil { log.Fatalln(err) } }
Por fim, vamos iterar essa variável e printar seu resultado no terminal.
func main() { resp, err := http.Get("https://jsonplaceholder.typicode.com/posts") if err != nil { log.Fatalln(err) } body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatalln(err) } defer resp.Body.Close() var posts []Post err = json.Unmarshal(body, &posts) if err != nil { log.Fatalln(err) } for _, post := range posts { log.Printf("%+v\n", post) } }
Agora é só fazer um go run main.go
e ver o resultado.
Post
Para requisições do tipo POST, vamos importar 5 packages.
bytes
para criar um objeto que implemente a interface io.Reader
;encoding/json
para fazer o encode do nosso payload;io/ioutil
para fazer leitura da resposta;log
para logar os erros;net/http
para executar a requisição.
Para começar, vamos criar nosso payload usando um map
, fazer seu encode com a função json.Marshal
e criar o objeto que implementa a interface io.Reader
com a função bytes.NewBuffer
.
func main() { body, _ := json.Marshal(map[string]string{ "nome": "Tiago Temporin", "idade": 32, }) payload := bytes.NewBuffer(body) }
Com o payload pronto, vamos utilizar a função http.Post
para fazer a requisição. Essa função espera 3 parâmetros, sendo eles a URL, o content-type e o payload.
func main() { body, _ := json.Marshal(map[string]string{ "nome": "Tiago Temporin", "idade": 32, }) payload := bytes.NewBuffer(body) resp, err := http.Post("https://postman-echo.com/post", "application/json", payload) if err != nil { log.Fatalln(err) } }
Para finalizar, vamos ler a resposta, assim como fizemos para o GET, e printa-la como uma string no terminal.
func main() { body, _ := json.Marshal(map[string]string{ "nome": "Tiago Temporin", "idade": 32, }) payload := bytes.NewBuffer(body) resp, err := http.Post("https://postman-echo.com/post", "application/json", payload) if err != nil { log.Fatalln(err) } body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatalln(err) } defer resp.Body.Close() log.Printf("%s", body) }
Agora é só fazer o go run main.go
e ver o resultado.
GET, POST, PUT, PATCH, DELETE…
As duas formas de fazer uma requisição mostradas até aqui são bem simples de serem utilizadas, porém são um pouco limitadas, já que, por exemplo, não conseguimos editar nenhum item do cabeçalho da requisição.
Para esses casos temos a função http.NewRequest
. Essa função aceita 3 parâmetros, sendo eles o tipo de request (GET, POST, PUT..), a URL e o payload (use nil para quando não precisar enviar nada).
Como exemplo, vamos reescrever o exemplo do POST utilizando a função http.NewRequest
.
Primeira coisa que vamos fazer é adicionar uma variável global chamada client
. Essa variável vai conter o cliente http responsável pela execução das requisições.
var client = &http.Client{} func main() { body, _ := json.Marshal(map[string]string{ "nome": "Tiago Temporin", "idade": 32, }) payload := bytes.NewBuffer(body) }
Agora vamos mudar a chamada da função http.Post
para http.NewRequest
e, após validar se houve algum erro, adicionar um cabeçalho com o content-type da requisição.
var client = &http.Client{} func main() { body, _ := json.Marshal(map[string]string{ "nome": "Tiago Temporin", "idade": 32, }) payload := bytes.NewBuffer(body) req, err := http.NewRequest(http.MethodPost, "https://postman-echo.com/post", payload) if err != nil { log.Fatalln(err) } req.Header.Add("Content-Type", "application/json") }
Feita essa mudança, vamos executar a requisição com o método (*http.Client).Do
.
var client = &http.Client{} func main() { body, _ := json.Marshal(map[string]string{ "nome": "Tiago Temporin", "idade": 32, }) payload := bytes.NewBuffer(body) req, err := http.NewRequest(http.MethodPost, "https://postman-echo.com/post", payload) if err != nil { log.Fatalln(err) } req.Header.Add("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { log.Fatalln(err) } }
Após a requisição ter sido a executada, vamos ler a resposta. Essa parte é igual ao exemplo anterior.
var client = &http.Client{} func main() { body, _ := json.Marshal(map[string]string{ "nome": "Tiago Temporin", "idade": 32, }) payload := bytes.NewBuffer(body) req, err := http.NewRequest(http.MethodPost, "https://postman-echo.com/post", payload) if err != nil { log.Fatalln(err) } req.Header.Add("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { log.Fatalln(err) } body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatalln(err) } defer resp.Body.Close() log.Printf("%s", body) }
Agora é só executar o código com um go run main.go
e ver o resultado.
Deixem suas dúvidas nos comentários.
Até a próxima!