Server-Side Scripting/Document Databases/Go
routes/lesson10.go
edit// This program creates and displays a temperature database
// with options to insert, update, and delete records.
//
// References:
// https://golang.org/doc/
// https://www.mongodb.com/languages/golang
//
// Requires a Mongo installation to manage the database.
// Use of a Docker container is recommended.
// See https://en.wikiversity.org/wiki/Docker/MongoDB .
// If both the Node website and Mongo are running in containers,
// use 172.17.0.2 for the mongodb host address.
// If the Node website and/or Mongo are running locally, use 127.0.0.1
// for the mongodb host address.
package routes
import (
"context"
"html/template"
"log"
"net/http"
"path/filepath"
"strconv"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
// const HOST = "mongodb://172.17.0.2";
const HOST = "mongodb://127.0.0.1";
// const HOST = "mongodb://mongo-server"
const DATABASE = "temperature"
const COLLECTION = "countries"
func Lesson10(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 = processGet10()
case "POST":
result = processPost10(request)
default:
result = "Unexpected request method: " + request.Method
}
data := Data{template.HTML(result)}
path := filepath.Join("templates", "lesson10.html")
parsed, _ := template.ParseFiles(path)
parsed.Execute(response, data)
}
func processGet10() string {
result := getData10()
return result
}
func processPost10(request *http.Request) string {
country := request.FormValue("country")
temperature := request.FormValue("temperature")
if !countryExists10(country) {
insertCountry10(country, temperature)
} else if (temperature != "") {
updateCountry10(country, temperature)
} else {
deleteCountry10(country)
}
result := getData10()
return result
}
func getData10() string {
client, err := mongo.NewClient(options.Client().ApplyURI(HOST))
if err != nil {
log.Fatal(err)
}
ctxt, _ := context.WithTimeout(context.Background(), 10 * time.Second)
err = client.Connect(ctxt)
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(ctxt)
collection := client.Database(DATABASE).Collection(COLLECTION)
cursor, err := collection.Find(ctxt, bson.M{})
if err != nil {
log.Fatal(err)
}
defer cursor.Close(ctxt)
var documents []bson.M
err = cursor.All(ctxt, &documents)
if err != nil {
log.Fatal(err)
}
result := formatDocuments10(documents)
return result;
}
func formatDocuments10(documents []bson.M) string {
result := "<table><tr><th>ID</th>"
result += "<th>Country</th>"
result += "<th>Temperature</th></tr>"
for _, document := range documents {
id := document["_id"].(primitive.ObjectID)
country := document["country"].(string)
temperature := document["temperature"].(float64)
result += "<tr><td>" + id.Hex() + "</td>"
result += "<td>" + country + "</td>"
result += "<td>" + strconv.FormatFloat(temperature, 'f', 1, 64) + "</td></tr>"
}
result += "</table>"
return result
}
func countryExists10(country string) bool {
client, err := mongo.NewClient(options.Client().ApplyURI(HOST))
if err != nil {
log.Fatal(err)
}
ctxt, _ := context.WithTimeout(context.Background(), 10 * time.Second)
err = client.Connect(ctxt)
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(ctxt)
collection := client.Database(DATABASE).Collection(COLLECTION)
filter := bson.D {
{"country", country},
}
count, err := collection.CountDocuments(ctxt, filter)
if err != nil {
log.Fatal(err)
}
return count == 1
}
func insertCountry10(country string, temperature string) {
value, err := strconv.ParseFloat(temperature, 32)
if err != nil {
log.Fatal(err)
}
client, err := mongo.NewClient(options.Client().ApplyURI(HOST))
if err != nil {
log.Fatal(err)
}
ctxt, _ := context.WithTimeout(context.Background(), 10 * time.Second)
err = client.Connect(ctxt)
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(ctxt)
collection := client.Database(DATABASE).Collection(COLLECTION)
document := bson.D {
{"country", country},
{"temperature", value},
}
_, err = collection.InsertOne(ctxt, document)
if err != nil {
log.Fatal(err)
}
}
func updateCountry10(country string, temperature string) {
value, err := strconv.ParseFloat(temperature, 32)
if err != nil {
log.Fatal(err)
}
client, err := mongo.NewClient(options.Client().ApplyURI(HOST))
if err != nil {
log.Fatal(err)
}
ctxt, _ := context.WithTimeout(context.Background(), 10 * time.Second)
err = client.Connect(ctxt)
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(ctxt)
collection := client.Database(DATABASE).Collection(COLLECTION)
filter := bson.M {
"country": country,
}
update := bson.D{
{"$set", bson.D{{"temperature", value}}},
}
_, err = collection.UpdateOne(ctxt, filter, update)
if err != nil {
log.Fatal(err)
}
}
func deleteCountry10(country string) {
client, err := mongo.NewClient(options.Client().ApplyURI(HOST))
if err != nil {
log.Fatal(err)
}
ctxt, _ := context.WithTimeout(context.Background(), 10 * time.Second)
err = client.Connect(ctxt)
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(ctxt)
collection := client.Database(DATABASE).Collection(COLLECTION)
filter := bson.M {
"country": country,
}
_, err = collection.DeleteOne(ctxt, filter)
if err != nil {
log.Fatal(err)
}
}
templates/lesson10.html
edit<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Lesson 10</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Temperature Data Entry</h1>
<p>Enter country and temperature. Enter again to update.</p>
<p>Enter country without temperature to delete.</p>
<form method="POST">
<p><label for="country">Country:</label>
<input type="text" id="country" name="country" required>
</p>
<p><label for="stop">Temperature:</label>
<input type="text" id="temperature" name="temperature">
</p>
<p><input type="submit" name="submit" value="Submit"></p>
</form>
<hr>
{{.Table}}
</body>
</html>
Try It
editSee Server-Side Scripting/Routes and Templates/Go to create a test environment.