Server-Side Scripting/Associative Arrays/Go
Appearance
routes/lesson7.go
[edit | edit source]// This program reads a user-selected text file of countries
// and Celsius temperatures. It displays the data in Celsius
// and Fahrenheit sorted in descending order by temperature.
//
// File format:
// Country,MaximumTemperature
// Bulgaria,45.2 °C
// Canada,45 °C
//
// References:
// https://www.mathsisfun.com/temperature-conversion.html
// https://golang.org/doc/
// https://tutorialedge.net/golang/go-file-upload-tutorial/
// https://gobyexample.com/structs
package routes
import (
"html/template"
"io/ioutil"
"net/http"
"mime/multipart"
"path/filepath"
"sort"
"strconv"
"strings"
)
type Temperature7 struct {
country string
celsius float64
fahrenheit float64
}
func Lesson7(response http.ResponseWriter, request *http.Request) {
response.Header().Set("Content-Type", "text/html; charset=utf-8")
type Data struct {
Table template.HTML
}
result := ""
switch request.Method {
case "GET":
result = ""
case "POST":
file, handler, err := request.FormFile("file")
result = "<h2>" + handler.Filename + "</h2>"
if err != nil {
result += err.Error()
} else {
result += processFile7(file);
}
default:
result = "Unexpected request method: " + request.Method
}
data := Data{template.HTML(result)}
path := filepath.Join("templates", "lesson7.html")
parsed, _ := template.ParseFiles(path)
parsed.Execute(response, data)
}
func processFile7(file multipart.File) string {
bytes, err := ioutil.ReadAll(file)
if (err != nil) {
return err.Error()
}
text := string(bytes)
text = strings.TrimSpace(text)
lines := strings.Split(text, "\n")
if strings.Index(lines[0], "Country,MaximumTemperature") == 0 {
// remove heading line
lines = lines[1:]
}
var table []Temperature7
for _, line := range lines {
temperature := processLine7(line)
table = append(table, temperature)
}
sort.Slice(table, func(a, b int) bool {
return table[a].celsius > table[b].celsius
})
result := formatTable7(table)
return result
}
func processLine7(line string) Temperature7 {
slice := strings.Split(line, ",")
if len(slice) != 2 {
return Temperature7{"Invalid file format: ", 0, 0}
}
index := strings.Index(slice[1], " °C")
if index < 0 {
return Temperature7{"Invalid file format: ", 0, 0}
}
celsius, err := strconv.ParseFloat(slice[1][0:index], 64)
if err != nil {
return Temperature7{err.Error(), 0, 0}
}
fahrenheit := celsius * 9 / 5 + 32
temperature := Temperature7{
country: slice[0],
celsius: celsius,
fahrenheit: fahrenheit}
return temperature
}
func formatTable7(table []Temperature7) string {
result := "<table><tr><th>Country</th>"
result += "<th>Celsius</th><th>Fahrenheit</th></tr>"
for _, temperature := range table {
result += "<tr><td>" + temperature.country + "</td>"
result += "<td>" + strconv.FormatFloat(temperature.celsius, 'f', 1, 64) + "° C</td>"
result += "<td>" + strconv.FormatFloat(temperature.fahrenheit, 'f', 1, 64) + "° F</td></tr>"
}
result += "</table>"
return result
}
templates/lesson7.html
[edit | edit source]<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Lesson 7</title>
<link rel="stylesheet" href="styles.css">
<style>
p {
min-height: 1em;
}
</style>
</head>
<body>
<h1>Temperature Conversion</h1>
<p>Select a file of Celsius temperatures for conversion:</p>
<form method="POST" enctype="multipart/form-data">
<input type="file" id="file" name="file">
<input type="submit">
</form>
{{.Table}}
</body>
</html>
Try It
[edit | edit source]See Server-Side Scripting/Routes and Templates/Go to create a test environment.