How to load weather data using Google’s Go language

Google Go, also referred to as Golang, is an open-source programming language developed by Google.  Launched in 2009, Go was designed with a focus on simplicity, efficiency, and readability.  It especially excels in building networked and distributed systems and is particularly known for its fast compilation speed.  With a growing community and support from major tech companies, Go has gained popularity for its ability to deliver high-performance applications with a straightforward and expressive language syntax, and it is well suited to data driven applications such as using weather data.

To use the Visual Crossing Timeline API within the Go programming language, you can use the standard net/http package for making HTTP requests and a JSON parsing library such as encoding/json to handle the API responses.  Below is a simple example that demonstrates how to fetch weather data from the Visual Crossing Timeline API using Go.

First, you need to install an HTTP client library if you don’t already have one.  One popular choice is Resty.  Once this package is installed, you can use the following Go code to fetch weather data from the Visual Crossing Timeline API and print a simple result.

Sample Code

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"time"

	"github.com/go-resty/resty/v2"
)

const apiKey = "YOUR_API_KEY"
const apiEndpoint = "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/"

type WeatherResponse struct {
	Days []struct {
		Date        string `json:"datetimeStr"`
		Temperature float64
		Precipitation float64
		// Add more fields as needed
	} `json:"days"`
}

func main() {
	location := "New York, NY"
	startDate := time.Now().Format("2006-01-01")
	endDate := time.Now().Format("2006-01-03")

	client := resty.New()

	resp, err := client.R().
		SetQueryParam("key", apiKey).
		SetQueryParam("location", location).
		SetQueryParam("startDate", startDate).
		SetQueryParam("endDate", endDate).
		SetHeader("Content-Type", "application/json").
		Get(apiEndpoint)

	if err != nil {
		log.Fatalf("Error making request: %v", err)
	}

	if resp.StatusCode() != 200 {
		log.Fatalf("Error: %v", resp)
	}

	var weatherData WeatherResponse
	err = json.Unmarshal(resp.Body(), &weatherData)
	if err != nil {
		log.Fatalf("Error decoding JSON response: %v", err)
	}

	// Print weather data
	fmt.Printf("Weather for %s from %s to %s:\n", location, startDate, endDate)
	for _, day := range weatherData.Days {
		fmt.Printf("Date: %s, Temperature: %.2f°C, Precipitation: %.2fmm\n", day.Date, day.Temperature, day.Precipitation)
	}
}

(Before using this code directly, make sure to replace “YOUR_API_KEY” with your actual Visual Crossing API key.  You can obtain a free API key by signing up for a Visual Crossing Weather account.)

This example fetches the weather forecast for a given period (January 1, 2006 through January 3, 2006) for a specified location (New York, NY).  You can adjust the parameters and response structure according to your specific requirements. For more information on how to do that, keep reading.

Understanding the sample

Let’s break this code sample down into sections, to better understand what it is doing in detail.

The first part of the code simply sets up our imports and constants.  The constants include our API Key as well as the endpoint URL for the Visual Crossing Weather Timeline API service. These will not change during the lift of our sample.

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"time"

	"github.com/go-resty/resty/v2"
)

const apiKey = "YOUR_API_KEY"
const apiEndpoint = "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/"

The next portion of the code defines a structure to hold our parsed weather data.  In this simple example, we are only interested in reporting forecasted temperature and precipitation.  So, we limit our structure to only those values along with the date.  Go will take care of parsing these values for us from the result data. Note that we can extend this structure as needed to manage additional weather data measures depending upon our use case.

type WeatherResponse struct {
	Days []struct {
		Date        string `json:"datetimeStr"`
		Temperature float64
		Precipitation float64
		// Add more fields as needed
	} `json:"days"`
}

Following that, we have the first part of our main function.  This sets up the locations and dates as variables.  It then builds a new request using the constants and variables that we populated.   After the request has completed, we check the results for error conditions before moving on to the parsing phase.

func main() {
	location := "New York, NY"
	startDate := time.Now().Format("2006-01-01")
	endDate := time.Now().Format("2006-01-03")

	client := resty.New()

	resp, err := client.R().
		SetQueryParam("key", apiKey).
		SetQueryParam("location", location).
		SetQueryParam("startDate", startDate).
		SetQueryParam("endDate", endDate).
		SetHeader("Content-Type", "application/json").
		Get(apiEndpoint)

	if err != nil {
		log.Fatalf("Error making request: %v", err)
	}

	if resp.StatusCode() != 200 {
		log.Fatalf("Error: %v", resp)
	}

If our request succeeded, we now have a query result to parse.  We use Go’s JSON parser to parse the JSON response into our WeatherResponse structure that we defined earlier. It will automatically find the specific weather measured specified in our structure.

	var weatherData WeatherResponse
	err = json.Unmarshal(resp.Body(), &weatherData)
	if err != nil {
		log.Fatalf("Error decoding JSON response: %v", err)
	}

	// Print weather data
	fmt.Printf("Weather for %s from %s to %s:\n", location, startDate, endDate)
	for _, day := range weatherData.Days {
		fmt.Printf("Date: %s, Temperature: %.2f°C, Precipitation: %.2fmm\n", day.Date, day.Temperature, day.Precipitation)
	}
}

Finally, we loop through the parsed result data and print the historical weather data for each day of our query. A more useful implementation might store the results in a database or use them as the basis for a detailed weather analysis based on other business data.

	// Print weather data
	fmt.Printf("Weather for %s from %s to %s:\n", location, startDate, endDate)
	for _, day := range weatherData.Days {
		fmt.Printf("Date: %s, Temperature: %.2f°C, Precipitation: %.2fmm\n", day.Date, day.Temperature, day.Precipitation)
	}
}

This is just a sample that has been simplified to show the basic flow of querying data and parsing Visual Crossing Weather JSON results in Go.  Obviously, production code would be more careful in handling error cases and more flexible in the data being queried.  However, this should give any Go coder a good starting point to use when developing your own Go weather applications.

Questions or need help?

If you have a question or need help, please post on our actively monitored forum for the fastest replies. You can also contact us via our support site or drop us an email at support@visualcrossing.com.