Table of Contents
Introduction
In this tutorial, we will be creating a Go-based command-line weather app. The app will allow users to retrieve weather information for a specific location by making API requests. By the end of the tutorial, you will have a functional weather app that can be used from the command line.
Prerequisites
Before starting this tutorial, you should have a basic understanding of the Go programming language. Familiarity with concepts such as functions, variables, and API requests will be helpful. You will also need to have Go installed on your system.
Setting Up
To begin, let’s set up a new Go project. Open your terminal and create a new directory for the project:
mkdir weather-app
cd weather-app
Next, initialize a new Go module:
go mod init github.com/your-username/weather-app
We will be using a third-party library called “cobra” for building the command-line interface. Install it by running the following command:
go get -u github.com/spf13/cobra/cobra
Now, let’s create the main file for our project:
touch main.go
Open main.go
in a text editor and import the required packages:
package main
import (
"fmt"
"github.com/spf13/cobra"
)
Building the Weather App
Now that we have set up the project, let’s start building the command-line weather app. We will be using the OpenWeatherMap API to retrieve weather data.
Step 1: Define the CLI Commands and Flags
First, let’s define the CLI commands and flags using the “cobra” library. Modify main.go
as follows:
package main
import (
"fmt"
"github.com/spf13/cobra"
)
func main() {
var rootCmd = &cobra.Command{
Use: "weather",
Short: "A command-line weather app",
Long: "A command-line weather app that retrieves weather information for a specific location.",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Welcome to the Weather App!")
},
}
var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the version number of the Weather App",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Weather App v1.0")
},
}
var city string
var apiKey string
var currentWeatherCmd = &cobra.Command{
Use: "current",
Short: "Get the current weather for a specific city",
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("Retrieving current weather information for %s...\n", city)
// Implement API request logic here
},
}
currentWeatherCmd.Flags().StringVarP(&city, "city", "c", "", "Specify the city")
currentWeatherCmd.Flags().StringVarP(&apiKey, "apikey", "k", "", "Specify the API key")
rootCmd.AddCommand(versionCmd)
rootCmd.AddCommand(currentWeatherCmd)
rootCmd.Execute()
}
In the above code, we have defined three commands: version
, current
, and the default root command. The version
command prints the version number of our app. The current
command retrieves the current weather information for a specific city.
The current
command accepts two flags: --city
(or -c
) to specify the city and --apikey
(or -k
) to provide the OpenWeatherMap API key.
Step 2: Make API Requests
Next, let’s implement the logic to make API requests and retrieve weather information.
We will be using the http
package to make HTTP GET requests. Import the package at the top of the main.go
file:
import (
"fmt"
"github.com/spf13/cobra"
"io/ioutil"
"net/http"
)
Add the following code inside the Run
function of the currentWeatherCmd
command:
func(cmd *cobra.Command, args []string) {
fmt.Printf("Retrieving current weather information for %s...\n", city)
url := fmt.Sprintf("https://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s", city, apiKey)
response, err := http.Get(url)
if err != nil {
fmt.Println("Error making API request:", err)
return
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {
fmt.Println("Error reading API response:", err)
return
}
fmt.Println("API response:", string(body))
}
In the above code, we use fmt.Sprintf
to construct the API URL using the provided city and API key. Then, we use http.Get
to make a GET request to the API URL. We read the response body using ioutil.ReadAll
and print it to the console.
Step 3: Handling Errors
Let’s enhance our code to handle errors gracefully. Replace the existing code inside the currentWeatherCmd.Run
function with the following:
func(cmd *cobra.Command, args []string) {
fmt.Printf("Retrieving current weather information for %s...\n", city)
url := fmt.Sprintf("https://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s", city, apiKey)
response, err := http.Get(url)
if err != nil {
fmt.Println("Error making API request:", err)
return
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
fmt.Println("API request failed with status code:", response.StatusCode)
return
}
body, err := ioutil.ReadAll(response.Body)
if err != nil {
fmt.Println("Error reading API response:", err)
return
}
fmt.Println("API response:", string(body))
}
In the updated code, we check the HTTP status code of the API response. If it is not 200 (OK), we print an error message. This helps us handle cases where the API request itself was successful, but the response indicates an error.
Conclusion
In this tutorial, we have created a Go-based command-line weather app using the “cobra” library. We explored how to define CLI commands and flags, make API requests, and handle errors. You should now have a functional weather app that can be used from the command line.
Feel free to expand on this app by adding more features, such as forecast information or additional command-line options. Happy coding!