É 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/ioutilpara fazer leitura da resposta;logpara logar os erros;net/httppara 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.
bytespara criar um objeto que implemente a interface io.Reader;encoding/jsonpara fazer o encode do nosso payload;io/ioutilpara fazer leitura da resposta;logpara logar os erros;net/httppara 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!
Faça parte da comunidade!
Receba os melhores conteúdos sobre Go, Kubernetes, arquitetura de software, Cloud e esteja sempre atualizado com as tendências e práticas do mercado.
Livros Recomendados
Abaixo listei alguns dos melhores livros que já li sobre GO.




