-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
122 lines (103 loc) · 2.73 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package main
import (
"flag"
"fmt"
"log"
"net/http"
"os"
"strings"
"time"
)
const (
WeatherPeriodCurrent = "current"
WeatherPeriodMinutely = "minutely"
WeatherPeriodHourly = "hourly"
WeatherPeriodDaily = "daily"
UnitsImperial = "imperial"
UnitsMetric = "metric"
)
var httpClient http.Client
func exitInvalidArguments() {
println("\nUsage: go-weather [ -period=current|hourly|daily ] [ -units=C|F ] <location>...\n")
flag.Usage()
println()
os.Exit(2)
}
func main() {
httpClient = http.Client{
Timeout: time.Second * 10,
}
units := flag.String("units", "C", "C | F")
period := flag.String("period", "current", "current | hourly | daily")
flag.Parse()
places := flag.Args()
if len(places) < 1 {
exitInvalidArguments()
}
var un string
if strings.ToUpper(*units) == "C" {
un = UnitsMetric
} else if strings.ToUpper(*units) == "F" {
un = UnitsImperial
} else {
exitInvalidArguments()
}
if *period != WeatherPeriodCurrent &&
*period != WeatherPeriodHourly &&
*period != WeatherPeriodDaily {
exitInvalidArguments()
}
chs := make([]chan OpenWeatherResponseOneCall, len(places))
errChs := make([]chan error, len(places))
start := time.Now()
for i, place := range places {
chs[i] = make(chan OpenWeatherResponseOneCall, 1)
errChs[i] = make(chan error, 1)
go concurrentGetWeatherForPlace(place, un, *period, chs[i], errChs[i])
}
for i, ch := range chs {
w := <-ch
err := <-errChs[i]
if err != nil {
log.Fatal(err)
} else {
switch *period {
case WeatherPeriodCurrent:
printWeatherResult(*w.Current, places[i], un)
case WeatherPeriodHourly:
printWeatherResult(*w.Hourly, places[i], un)
case WeatherPeriodDaily:
printWeatherResult(*w.Daily, places[i], un)
}
}
}
elasped := time.Now().Sub(start)
fmt.Printf("Elasped time: %d\n", elasped.Milliseconds())
}
func getWeatherForPlace(place string, units string, period string) (w OpenWeatherResponseOneCall, err error) {
ll, err := getLatLngForPlace(place)
if err != nil {
return w, err
}
return getWeatherForLatLng(ll, units, period)
}
func concurrentGetWeatherForPlace(place string, units string, period string, wCh chan OpenWeatherResponseOneCall, errCh chan error) {
w, err := getWeatherForPlace(place, units, period)
wCh <- w
errCh <- err
}
func printWeatherResult(w interface{}, place string, units string) {
fmt.Printf("Weather for %s:\n", place)
switch w.(type) {
case OpenWeatherResponseCurrent:
fmt.Print(w.(OpenWeatherResponseCurrent).Output(units))
case []OpenWeatherResponseHourly:
for _, h := range w.([]OpenWeatherResponseHourly) {
fmt.Print(h.Output(units))
}
case []OpenWeatherResponseDaily:
for _, h := range w.([]OpenWeatherResponseDaily) {
fmt.Print(h.Output(units))
}
}
}