When you make a request to the OpenWeather API, the data you receive is in JSON format. JSON is a common data format used for exchanging information between a client and a server . However, itâs not always easy to read directly, especially when dealing with weather data.
Letâs take a look at what theraw data
looks like when you request the weather information :
{
"name": "Paris",
"weather": [
{
"description": "cloudy"
}
],
"main": {
"temp": 20.07,
"humidity": 27
},
"wind": {
"speed": 6.37
},
"sys": {
"sunrise": 1743397954,
"sunset": 1743443005
}
}
The data is structured in a way that might be difficult for the user to understand directly. For example :
Now, letâs look at how we can fetch and display this raw JSON data in Go. Below is an example of a Go program that fetches the weather data from the OpenWeather API and prints out the raw JSON response.
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"github.com/joho/godotenv"
)
type WeatherResponse struct {
Name string `json:"name"`
Weather []struct {
Description string `json:"description"`
} `json:"weather"`
Main struct {
Temp float64 `json:"temp"`
Humidity int `json:"humidity"`
} `json:"main"`
Wind struct {
Speed float64 `json:"speed"`
} `json:"wind"`
Sys struct {
Sunrise int64 `json:"sunrise"`
Sunset int64 `json:"sunset"`
} `json:"sys"`
}
func main() {
// Load environment variables from .env file
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}
// Get the API key from environment variables
apiKey := os.Getenv("API_KEY")
if apiKey == "" {
log.Fatal("API_KEY is not set in .env file")
}
// Ask the user for a city name
var city string
fmt.Println("Enter the name of the city:")
fmt.Scanln(&city)
// Build the request URL
url := fmt.Sprintf("https://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s&units=metric&lang=fr", city, apiKey)
// Send the HTTP request
resp, err := http.Get(url)
if err != nil {
log.Fatal("Error sending request to OpenWeather API:", err)
}
defer resp.Body.Close()
// Check if the response is valid (HTTP status code 200)
if resp.StatusCode != 200 {
log.Fatalf("Error: API status code = %d", resp.StatusCode)
}
// Decode the JSON response into the WeatherResponse struct
var weatherData WeatherResponse
err = json.NewDecoder(resp.Body).Decode(&weatherData)
if err != nil {
log.Fatal("Error decoding JSON response:", err)
}
// Print out the raw JSON for inspection
fmt.Println("Raw JSON Response:")
weatherJson, _ := json.MarshalIndent(weatherData, "", " ")
fmt.Println(string(weatherJson))
}
WeatherResponse
).json.MarshalIndent()
.copie this code in yourmain.go
file and excute it :
go run main.go
You should see something like this :
Enter the name of the city:
Paris
Raw JSON Response:
{
"name": "Paris",
"weather": [
{
"description": "ciel dégagé"
}
],
"main": {
"temp": 10.82,
"humidity": 57
},
"wind": {
"speed": 7.2
},
"sys": {
"sunrise": 1743571556,
"sunset": 1743618122
}
}
In the previous step, we displayed the raw JSON response from the OpenWeather API . However, while this data is useful, it's not very user-friendly. In this step, we will improve :
Instead of printing raw JSON, we will extract and format the important details in a way that is easier to understand.
Hereâs how we can improve the output :
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"time"
"github.com/joho/godotenv"
)
// Struct to store the weather API response
type WeatherResponse struct {
Name string `json:"name"`
Weather []struct {
Description string `json:"description"`
} `json:"weather"`
Main struct {
Temp float64 `json:"temp"`
Humidity int `json:"humidity"`
} `json:"main"`
Wind struct {
Speed float64 `json:"speed"`
} `json:"wind"`
Sys struct {
Sunrise int64 `json:"sunrise"`
Sunset int64 `json:"sunset"`
} `json:"sys"`
}
func main() {
// Load the .env file
err := godotenv.Load()
if err != nil {
log.Fatal("Error: Unable to load .env file. Make sure it exists and contains your API key.")
}
// Retrieve the API key from environment variables
apiKey := os.Getenv("API_KEY")
if apiKey == "" {
log.Fatal("Error: API_KEY is missing. Please check your .env file.")
}
// Ask the user for a city name
var city string
fmt.Print("Enter the name of the city: ")
fmt.Scanln(&city)
// Construct the API request URL
url := fmt.Sprintf("https://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s&units=metric", city, apiKey)
// Send the HTTP request
resp, err := http.Get(url)
if err != nil {
log.Fatal("Error: Unable to connect to OpenWeather API. Please check your internet connection.")
}
defer resp.Body.Close()
// Check if the API response is successful
if resp.StatusCode != 200 {
log.Fatalf("Please check the city name and try again.")
}
// Decode the JSON response into our struct
var weatherData WeatherResponse
err = json.NewDecoder(resp.Body).Decode(&weatherData)
if err != nil {
log.Fatal("Error: Unable to process the weather data.")
}
// Convert sunrise and sunset timestamps to readable time format
sunriseTime := time.Unix(weatherData.Sys.Sunrise, 0).Format("15:04")
sunsetTime := time.Unix(weatherData.Sys.Sunset, 0).Format("15:04")
// Display the formatted weather information
fmt.Println("\n Weather Information:")
fmt.Println("---------------------------")
fmt.Printf(" City: %s\n", weatherData.Name)
fmt.Printf(" Condition: %s\n", weatherData.Weather[0].Description)
fmt.Printf(" Temperature: %.2f°C\n", weatherData.Main.Temp)
fmt.Printf(" Humidity: %d%%\n", weatherData.Main.Humidity)
fmt.Printf(" Wind Speed: %.2f m/s\n", weatherData.Wind.Speed)
fmt.Printf(" Sunrise: %s AM\n", sunriseTime)
fmt.Printf(" Sunset: %s PM\n", sunsetTime)
fmt.Println("---------------------------")
}
copie this code in yourmain.go
file and excute it :
go run main.go
You should see something like this :
Enter the name of the city: london
Weather Information:
---------------------------
City: London
Condition: clear sky
Temperature: 12.78°C
Humidity: 60%
Wind Speed: 9.77 m/s
Sunrise: 07:33 AM
Sunset: 20:34 PM
---------------------------
Youâve successfully built a weather app in Go! đ Along the way, you learned how to interact with an external API, handle JSON responses, manage environment variables securely, and improve data display.
đ Thank you for reading these articles! If you find this content valuable and want to support my work, a coffee would be greatly appreciated! âđ
đ» I am a freelance web developer, and I personally create and maintain this website. Any support would help me improve and expand it further! đ