Please note, this is a STATIC archive of website www.tutorialspoint.com from 11 May 2019, cach3.com does not collect or store any user information, there is no "phishing" involved.
package main
import (
"fmt"
"net/http"
"strings"
"io/ioutil"
"strconv"
"regexp"
)
var load_station = "KIAH"
var url = fmt.Sprintf("https://w1.weather.gov/data/METAR/%s.1.txt", load_station)
// Data structure that will get returned by the bellow functions
// Here I am defining each variable and what type of data that variable holds
type StationData struct {
station string
statute_miles int
scatter int
overcast int
slp int
}
// This is uses the split function to go though every line, and every item in that line
// If the specific item matches any of the wanted fields, we set its value in data
func simple(lines []string) (StationData) {
// Creates a new instance of StationData structure
data := StationData{}
// Loops through every line
for _, line := range lines {
// Splits each line by spaces, so we can process each item independently
parts := strings.Split(line, " ")
if len(parts) == 0 {
// Skip lines with no data
continue
}
// If the line begins with METAR we know the next item in the line is the station
if parts[0] == "METAR" {
data.station = parts[1]
}
// Loop through ever other part in the line and see if it matches any fields we want
for _, part := range parts {
if len(part) < 3 {
// Skip anything less than 3 characters in length
continue
}
// Get the last 2 characters, and see if it equals SM
if part[len(part)-2:] == "SM" {
// Get all characters stopping 2 characters from the end (to ignore SM)
data.statute_miles, _ = strconv.Atoi(part[:len(part)-2])
} else if part[:len(part)-3] == "SCT" {
data.scatter, _ = strconv.Atoi(part[3:])
} else if part[:len(part)-3] == "OVC" {
data.overcast, _ = strconv.Atoi(part[3:])
} else if part[:len(part)-3] == "SLP" {
data.slp, _ = strconv.Atoi(part[3:])
}
}
}
return data
}
// This uses regex to parse the lines, rather than looping through each item ourselves
func regex(lines []string) (StationData) {
data := StationData{}
// Anything between ( and ) parentheses are going to be captures.
// Here we are attempting to gather all possible fields we are looking for
re := regexp.MustCompile(`^METAR\s([^\s]+)|([0-9]+)SM|SCT([0-9]+)|OVC([0-9]+)|SLP([0-9]+)`)
for _, line := range lines {
// Loop through each line, and attempt to find all possible matches
part_groups := re.FindAllStringSubmatch(line, -1)
// Loop through all results. The order of the parentheses's, determine the location in the array
// so we can count the left parenthesis, to know what index to use
for _, parts := range part_groups {
// Station is 1 parenthesis in. If it has any data, then set the variable to its value
if len(parts[1]) != 0 {
data.station = parts[1]
} else if len(parts[2]) != 0 {
data.statute_miles, _ = strconv.Atoi(parts[2])
} else if len(parts[3]) != 0 {
data.scatter, _ = strconv.Atoi(parts[3])
} else if len(parts[4]) != 0 {
data.overcast, _ = strconv.Atoi(parts[4])
} else if len(parts[5]) != 0 {
data.slp, _ = strconv.Atoi(parts[5])
}
}
}
return data
}
func main() {
// Make an http request
response, err := http.Get(url)
// If an error occured, throw the error
if err != nil {
panic(err)
}
// When this function closes, also close io to the body
defer response.Body.Close()
// If the response is not 200 (OK) give an error
if response.StatusCode != 200 {
panic(fmt.Errorf("Failed to load file\n"))
} else {
// Read all response data (the file)
body, err := ioutil.ReadAll(response.Body)
// If it fails to read the data, throw an error
if err != nil {
panic(err)
}
// Split the file into individual lines
lines := strings.Split(string(body), "\n")
// Print the results from the functions
fmt.Printf("simple = %+v\n", simple(lines))
fmt.Printf("regex = %+v\n", regex(lines))
}
}