ML
    • Recent
    • Categories
    • Tags
    • Popular
    • Users
    • Groups
    • Register
    • Login

    Weather cli app

    IT Discussion
    1
    2
    142
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • stacksofplatesS
      stacksofplates
      last edited by stacksofplates

      So I've been trying to get better at development and have a deeper understanding of Go. I wrote a small utility to interface with openweathermap.org's API. I had an initial setup that didn't utilize interfaces or methods but I went back and refactored it so that I could add another weather service later if I wanted to. Interfaces allow you to call methods over multiple types. The app just takes two arguments, the city and country where you want the weather.

      I'll preface the code with the fact that this is most likely horrible and I'm sure a lot is done incorrectly, so feel free to tear this apart if you actually know what you're doing.

      main.go

      package main
      
      import (
              "os"
      )
      
      type Location struct {
              City    string
              Country string
      }
      
      type Getter interface {
              GetWeather()
      }
      
      func Weather(g Getter) {
              g.GetWeather()
      }
      
      func main() {
              city := os.Args[1]
              country := os.Args[2]
      
              place := Location{}
              place.City = city
              place.Country = country
      
              Weather(place)
      
      }
      

      openweathermap.go

      package main
      
      import (
              "encoding/json"
              "fmt"
              "log"
              "net/http"
              "os"
      
              ini "gopkg.in/ini.v1"
      )
      
      type OpenWeather struct {
              Coord struct {
                      Lon float64 `json:"lon"`
                      Lat float64 `json:"lat"`
              } `json:"coord"`
              Weather []struct {
                      ID          int    `json:"id"`
                      Main        string `json:"main"`
                      Description string `json:"description"`
                      Icon        string `json:"icon"`
              } `json:"weather"`
              Base string `json:"base"`
              Main struct {
                      Temp     float64 `json:"temp"`
                      Pressure int     `json:"pressure"`
                      Humidity int     `json:"humidity"`
                      TempMin  float64 `json:"temp_min"`
                      TempMax  float64 `json:"temp_max"`
              } `json:"main"`
              Visibility int `json:"visibility"`
              Wind       struct {
                      Speed float64 `json:"speed"`
                      Deg   int     `json:"deg"`
                      Gust  float64 `json:"gust"`
              } `json:"wind"`
              Rain struct {
                      OneH float64 `json:"1h"`
              } `json:"rain"`
              Snow struct {
                      OneH float64 `json:"1h"`
              } `json:"snow"`
              Clouds struct {
                      All int `json:"all"`
              } `json:"clouds"`
              Dt  int `json:"dt"`
              Sys struct {
                      Type    int     `json:"type"`
                      ID      int     `json:"id"`
                      Message float64 `json:"message"`
                      Country string  `json:"country"`
                      Sunrise int     `json:"sunrise"`
                      Sunset  int     `json:"sunset"`
              } `json:"sys"`
              ID   int    `json:"id"`
              Name string `json:"name"`
              Cod  int    `json:"cod"`
      }
      
      func (l Location) GetWeather() {
              config, err := ini.Load(".weather")
              if err != nil {
                      fmt.Printf("Failed to load config file %v", err)
                      os.Exit(1)
              }
      
              apiKey := config.Section("").Key("openweather").String()
      
              url := fmt.Sprintf("https://api.openweathermap.org/data/2.5/weather?q=%s,%s&units=imperial&appid=%s", l.City, l.Country, apiKey)
      
              req, err := http.NewRequest("GET", url, nil)
              if err != nil {
                      log.Fatal("NewRequest: ", err)
              }
      
              client := http.Client{}
      
              resp, err := client.Do(req)
              if err != nil {
                      log.Fatal("Do: ", err)
              }
      
              defer resp.Body.Close()
      
              var weather OpenWeather
      
              if err := json.NewDecoder(resp.Body).Decode(&weather); err != nil {
                      log.Println(err)
              }
      
              fmt.Println("Temperature: ", weather.Main.Temp)
              fmt.Println("Description: ", weather.Weather[0].Description)
              fmt.Println("Minimum Temperature: ", weather.Main.TempMin)
              fmt.Println("Maximum Temperature: ", weather.Main.TempMax)
              fmt.Println("Wind Speed: ", weather.Wind.Speed, " MPH")
      }
      

      It's looking for an ini file named .weather in the same directory as the application. The content should be

      openweather = <your_api_key>
      

      I only have a couple parts of the json returned, mostly because I'm lazy. I also have the imperial units hard coded because again, I'm lazy.

      weatherapp.png

      1 Reply Last reply Reply Quote 3
      • stacksofplatesS
        stacksofplates
        last edited by

        To build this, you can just create those two files and do a go build -o weather main.go openweathermap.go and it will generate your executable.

        To build it for a different platform (Windows vs Linux) pass the build environment variable in like this:

        GOOS=windows go build -o weather.exe main.go openweathermap.go
        
        1 Reply Last reply Reply Quote 2
        • 1 / 1
        • First post
          Last post