I just started to learn a bit about Golang. Im mainly a frontend developer but recently I started to use Neovim as my code editor and for some reason Im starting to like more the use of the terminal for coding and decided continuying exploring. And one clear option is Go. So I decided to build something small but useful, then I found this YouTube video about building a CLI in Go for checking the weather.
Initialize project
# You change crisecheverria for whatever username you want in your github repo
go mod init crisecheverria/weather
This command creates a Go Module go.mod
. It's a collection of Go packages with versioned dependencies.
Create a file main.go
:
package main
import "fmt"
func main() {
fmt.Println("Hello weather!")
}
You can test your code by running:
go run main.go
We're going to use Openweathermap API. You will need to create a variable WEATHERAPI_KEY with the value of the Openweather API KEY.
export WEATHERAPI_KEY=YOUR_KEY
Inside main.go
package main
import (
"fmt"
"os"
"net/http"
)
func main() {
apiKey := os.Getenv("WEATHERAPI_KEY")
if apiKey == "" {
fmt.Fprintln(os.Stderr, "Missing WEATHERAPI_KEY")
os.Exit(1)
}
location := "Gothenburg"
url := fmt.Sprintf("http://api.openweathermap.org/data/2.5/forecast?appid=%s&units=metric&q=%s", apiKey, location)
res, err := http.Get(url)
if err != nil {
fmt.Fprintf(os.Stderr, "Error fetching weather data: %v\n", err)
os.Exit(1)
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
fmt.Fprintf(os.Stderr, "Weather API returned non-200 status: %d\n", res.StatusCode)
os.Exit(1)
}
}
Some explanation:
apiKey := os.Getenv("WEATHERAPI_KEY")
if apiKey == "" {
fmt.Fprintln(os.Stderr, "Missing WEATHERAPI_KEY")
os.Exit(1)
}
We check for the WEATHERAPI_KEY
in our system. It it doesnt exists or if its empty we print a message to the user uaing system os.Stderr
function and terminate program execution with os.Exit(1)
you can also see that module os
needs to be imported in order to use Stderr
and Exit()
.
location := "Gothenburg"
url := fmt.Sprintf("http://api.openweathermap.org/data/2.5/forecast?appid=%s&units=metric&q=%s", apiKey, location)
res, err := http.Get(url)
if err != nil {
fmt.Fprintf(os.Stderr, "Error fetching weather data: %v\n", err)
os.Exit(1)
}
defer res.Body.Close()
We define a local variable location
and initialize it to Gothenburg
for now, later we will read user input arguments. Then we store the url string injecting the apiKey and location. After that we use http
module and make a Get
call, this methos returns two values we store them inside res
and err
. Also check if err
is diferent than nill
, which would mean we have an error from the endpoint, if case we print it.
And finally we close the http.Get response with defer res.Body.Close()
to esure that the HTTP response body is properly closed once it is no longer needed. This is critical in Go when working with HTTP to avoid resource leaks. By using defer
the response body is closed after the program finishes processing the response.
if res.StatusCode != http.StatusOK {
fmt.Fprintf(os.Stderr, "Weather API returned non-200 status: %d\n", res.StatusCode)
os.Exit(1)
}
We check if the response status code is different than 200, if it is we print the status code and exit the program.
body, err := io.ReadAll(res.Body)
if err != nil {
fmt.Fprintf(os.Stderr, "Error reading weather data: %v\n", err)
os.Exit(1)
}
fmt.Println(string(body))
We read the response body and store it in body
and check for errors. If there are no errors we print the body. Dont forget to add the io
module to the imports.
import "io"
Now lets run our program again:
go run main.go
By default the OpenWeather API returns a JSON response with a lot of information. You can use Postman to test the API and see the response.
This is for now the end if the first part of the tutorial. In the next part we will parse the JSON response and display the weather information in a more readable format.
Stay tuned! 🚀
Full code so far:
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
apiKey := os.Getenv("WEATHERAPI_KEY")
if apiKey == "" {
fmt.Fprintln(os.Stderr, "Missing WEATHERAPI_KEY")
os.Exit(1)
}
location := "Gothenburg"
url := fmt.Sprintf("http://api.openweathermap.org/data/2.5/forecast?appid=%s&units=metric&q=%s", apiKey, location)
res, err := http.Get(url)
if err != nil {
fmt.Fprintf(os.Stderr, "Error fetching weather data: %v\n", err)
os.Exit(1)
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
fmt.Fprintf(os.Stderr, "Error reading weather data: %v\n", err)
os.Exit(1)
}
fmt.Println(string(body))
}