47/100 Dias de Golang - Aplicação para buscar previsão do tempo - Parte 4
Table of Contents
#
Aplicação para buscar previsão do tempo - Parte 4
Vamos trabalhar com a formatação dos JSON’s nesse post. Atualmente estamos somente exibindo o retorno da API, vamos formatar e exibir somente os campos que temos interesse.
Vamo primeiro editar o arquivo cidade.go
. Devemos criar o formato de resposta do JSON. No nosso caso o JSON é uma lista de várias cidade com Nome, ID e Estado
type Cidade []struct {
Nome string `json:"nome"`
ID int `json:"id"`
Estado string `json:"estado"`
}
Na função requestsCidade
temos que definir uma variável do tipo Cidade
var cidades Cidade
E depois de receber a resposta da api devemos fazer o Unmarshal
do JSON.
err = json.Unmarshal(body, &cidades)
if err != nil {
log.Fatalf("Erro ao fazer parse do JSON: %v", err)
}
Depois tratamos a variável cidades como uma estrutura normal do Golang. Nesse caso faremos um for exibindo o Nome, ID e Estado
fmt.Println("\nCidades encontradas:")
for _, c := range cidades {
fmt.Printf("Nome: %s, ID: %d, Estado: %s\n", c.Nome, c.ID, c.Estado)
}
No arquivo tempo.go
temos uma estrutura um pouco mais complexa. Temos uma struct dentro de outra struct. Veja como é a resposta da API:
{
"cidade":"Curitiba",
"estado":"PR",
"atualizado_em":"2025-04-28",
"clima":[
{
"data":"2025-04-29",
"condicao":"pn",
"condicao_desc":"Parcialmente Nublado",
"min":13,
"max":22,
"indice_uv":0
}
]
}
Para definirmos essa struct, podemos fazer da seguinte forma:
type Info struct {
Cidade string `json:"cidade"`
Estado string `json:"estado"`
AtualizadoEm string `json:"atualizado_em"`
Clima []Clima `json:"clima"`
}
type Clima struct {
Data string `json:"data"`
Condicao string `json:"condicao"`
CondicaoDesc string `json:"condicao_desc"`
Min int `json:"min"`
Max int `json:"max"`
IndiceUv int `json:"indice_uv"`
}
A chave “clima” é definida como um slice
do tipo Clima
. Depois seguimos os mesmos passos do script de cidade.
var info Info
err = json.Unmarshal(body, &info)
if err != nil {
log.Fatalf("Erro ao fazer parse do JSON: %v", err)
}
fmt.Printf("\nPrevisão do tempo para %s/%s\n", info.Cidade, info.Estado)
fmt.Printf("Atualizado em: %s\n\n", info.AtualizadoEm)
for _, clima := range info.Clima {
fmt.Printf("Data: %s\n", clima.Data)
fmt.Printf("Condição: %s\n", clima.CondicaoDesc)
fmt.Printf("Temperatura: Mín %d°C - Máx %d°C\n", clima.Min, clima.Max)
fmt.Printf("Índice UV: %d\n\n", clima.IndiceUv)
}
Veja como fica a saída dos dois comando:
go run main.go cidade --cidade Curitiba
Cidades encontradas:
Nome: Curitiba, ID: 227, Estado: PR
Nome: Curitibanos, ID: 1728, Estado: SC
go run main.go tempo -i 227
Previsão do tempo para Curitiba/PR
Atualizado em: 2025-04-28
Data: 2025-04-29
Condição: Parcialmente Nublado
Temperatura: Mín 13°C - Máx 22°C
Índice UV: 0
Uma dica bem legal é o JSON-to-Go uma aplicação você coloca o JSON e ele retorna a struct formatada. Muito prático e fácil de usar.
Código final dos arquivos editados:
/*
Copyright © 2025 NAME HERE <EMAIL ADDRESS>
*/
package cmd
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"github.com/spf13/cobra"
)
var cidadeID string
type Info struct {
Cidade string `json:"cidade"`
Estado string `json:"estado"`
AtualizadoEm string `json:"atualizado_em"`
Clima []Clima `json:"clima"`
}
type Clima struct {
Data string `json:"data"`
Condicao string `json:"condicao"`
CondicaoDesc string `json:"condicao_desc"`
Min int `json:"min"`
Max int `json:"max"`
IndiceUv int `json:"indice_uv"`
}
// tempoCmd represents the tempo command
var tempoCmd = &cobra.Command{
Use: "tempo",
Short: "A brief description of your command",
Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
Run: func(cmd *cobra.Command, args []string) {
requestTempo(cidadeID)
},
}
func init() {
rootCmd.AddCommand(tempoCmd)
tempoCmd.Flags().StringVarP(&cidadeID, "cidadeID", "i", "1", "ID da cidade")
}
func requestTempo(cidadeID string) {
var info Info
url := fmt.Sprintf("https://brasilapi.com.br/api/cptec/v1/clima/previsao/%s", cidadeID)
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
log.Fatalf("Erro ao criar request: %v", err)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatalf("Erro ao fazer request: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatalf("Erro ao ler resposta: %v", err)
}
err = json.Unmarshal(body, &info)
if err != nil {
log.Fatalf("Erro ao fazer parse do JSON: %v", err)
}
fmt.Printf("\nPrevisão do tempo para %s/%s\n", info.Cidade, info.Estado)
fmt.Printf("Atualizado em: %s\n\n", info.AtualizadoEm)
for _, clima := range info.Clima {
fmt.Printf("Data: %s\n", clima.Data)
fmt.Printf("Condição: %s\n", clima.CondicaoDesc)
fmt.Printf("Temperatura: Mín %d°C - Máx %d°C\n", clima.Min, clima.Max)
fmt.Printf("Índice UV: %d\n\n", clima.IndiceUv)
}
}
package cmd
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"github.com/spf13/cobra"
)
var cidade string
type Cidade []struct {
Nome string `json:"nome"`
ID int `json:"id"`
Estado string `json:"estado"`
}
// cidadeCmd represents the cidade command
var cidadeCmd = &cobra.Command{
Use: "cidade",
Short: "Retorna uma listagem de cidades",
Long: `Retorna dados das cidades candidatas que possuem a string passada como parâmetro
exemplo de uso: cidadetempo --cidade Curitiba
`,
Run: func(cmd *cobra.Command, args []string) {
requestCidade(cidade)
},
}
func init() {
rootCmd.AddCommand(cidadeCmd)
cidadeCmd.Flags().StringVarP(&cidade, "cidade", "c", "Curitiba", "Cidade que você quer o ID")
}
func requestCidade(cidade string) {
var cidades Cidade
url := fmt.Sprintf("https://brasilapi.com.br/api/cptec/v1/cidade/%s", cidade)
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
log.Fatalf("Erro ao criar request: %v", err)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatalf("Erro ao fazer request: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatalf("Erro ao ler resposta: %v", err)
}
err = json.Unmarshal(body, &cidades)
if err != nil {
log.Fatalf("Erro ao fazer parse do JSON: %v", err)
}
fmt.Println("\nCidades encontradas:")
for _, c := range cidades {
fmt.Printf("Nome: %s, ID: %d, Estado: %s\n", c.Nome, c.ID, c.Estado)
}
}