Meine erste kleine GO Webanwendung

Da ich mich gerade in die Programmiersprache GO einarbeite, habe ich eine kleine Web-Anwendung erstellt. Die Seiten werden mit der GO-Templateengine erstellt und man kann den Vor- und Nachnamen einer Person Eingeben und Anzeigen lassen. Das ist natürlich nicht viel mehr als ein Hello-World, aber irgendwo muss man ja anfangen.

main.go

package main

import (
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"sync"
)

//var templates *template.Template
var person Person

func init() {
	/*	log.Print("init start")
		templates = template.Must(template.ParseGlob("templates/*.html"))
		log.Printf("init end, template=%v", templates)
	*/
	person.FirstName = "Max"
	person.LastName = "Mustermann"
}

func main() {
	http.HandleFunc("/", viewHandler)
	http.ListenAndServe(":8080", nil)
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
	url := r.URL.Path
	log.Printf("Path: %v", url)

	switch url {
	case "/":
		url = "/index"
	case "/sendperson":
		url = "/showperson"
		log.Printf("Method: %v", r.Method)
		updatePerson(r.FormValue("firstname"), r.FormValue("lastname"))
		log.Printf("FirstName: %v, LastName: %v", person.FirstName, person.LastName)
		http.Redirect(w, r, "/showperson", 301)
	}

	loadFile := fmt.Sprintf("templates%s.html", url)
	log.Printf("Template: %v", loadFile)

	layout, _ := template.ParseFiles("_layout.html")
	tmpl, _ := layout.Clone()

	f, err := os.Open(loadFile)
	if err != nil {
		log.Println(err)
		http.Redirect(w, r, "/", http.StatusNotFound)
	}
	content, _ := ioutil.ReadAll(f)
	f.Close()
	tmpl.Parse(string(content))

	//templates.ExecuteTemplate(w, "template.html", person)
	tmpl.Execute(w, person)
}

type Person struct {
	FirstName string
	LastName  string
}

func updatePerson(firstname, lastname string) {
	var mutex sync.Mutex
	mutex.Lock()
	person.FirstName = firstname
	person.LastName = lastname
	mutex.Unlock()
}

_layout.html

<!DOCTYPE html>
<html>
  <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

      {{template "header"}}
  </head>
  <body>
    {{template "body" .}}
  </body>
</html>

templates/index.html

{{define "body"}}
  <h1>Edit Person</h1>
  <form action="sendperson" id="person" method="POST">
  FirstName: {{.FirstName}}<br>
  LastName: {{.LastName}}<br>

  <label for="firstname">FirstName</label>
  <input type="text" name="firstname" id="firstname" maxlength="40" value="{{.FirstName}}">

 <label for="lastname">LastName</label>
 <input type="text" name="lastname" id="lastname" maxlength="40" value="{{.LastName}}">


 <button type="reset">Eingaben zurücksetzen</button>

 <button type="submit">Eingaben absenden</button>


</form>
{{end}}

{{define "header"}}{{end}}

templates/showperson.html

{{define "body"}}
  <h1>Show Person</h1>
  FirstName: {{.FirstName}}<br>
  LastName: {{.LastName}}<br>
  <a href="/">Edit</a>
{{end}}

{{define "header"}}{{end}}

Zu beachten ist, dass die Logik für die Templates “umgedreht” wurde. D.h. In das Layout wird die eigentliche Seite geladen. Normalerweise würde in der Seite ein Include für Header und Body etc. stehen …

Damit das funktioniert dürfen nicht alle Templates gemeinsam geladen werden, sondern für jede Seite zuerst das Layout dann der zugehörige “Seite” mit der “body”-Definition!