Golang HTML Template Hello World

2017-09-26

An example of rendering "Hello World!" using golang as a web server with it's built in "net/http" and "html/template" packages.

package main

import (
  "html/template"
  "log"
  "net/http"
)

func main() {
  mux := http.NewServeMux()

  server := &http.Server{
  Addr:    ":8080",
  Handler: mux,
  }

  layout, err := template.ParseFiles("layout.html.tmpl")
  if err != nil {
    log.Panic(err)
  }

  mux.HandleFunc("/", home(layout))

  log.Fatal(server.ListenAndServe())
}

func home(layout *template.Template) func(http.ResponseWriter, *http.Request) {
  return func(w http.ResponseWriter, r *http.Request) {
  err := layout.Execute(w, nil)
    if err != nil {
      log.Panic(err)
    }
  }
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>jdc</title>
  </head>
  <body>
    Hello World!
  </body>
</html>

Hello World!

The result isn't any different than our first example (except perhaps a change in font) but it is a step closer to something more useful to run in production.

package main

import (
  "html/template"
  "log"
  "net/http"
)

We've added one package "html/template" to our packages from the last example. This core library in golang gives us the html templates. We don't use any of the features this gives us in this example, but it sets the stage for something later.


func main() {
  mux := http.NewServeMux()

  server := &http.Server{
  Addr:    ":8080",
  Handler: mux,
  }

As before we create a http.ServeMux and register it to our newly created http.Server.


  layout, err := template.ParseFiles("home.html.tmpl")
  if err != nil {
    log.Panic(err)
  }

Parse the template file we have saved in the same directory as our go file which is named "home.html.tmpl". Store the parsed template as layout and check for errors. You'll often have errors in your templates so make sure to display or panic this error as we have done here.


  mux.HandleFunc("/", home(layout))

Pass our newly created template to the home function and register it to the "/" path.


  log.Fatal(server.ListenAndServe())
}

Open the port and start listening for requests.


func home(layout *template.Template) func(http.ResponseWriter, *http.Request) {

There is a bit going on here if you're new to golang. We've defined a new function home which accepts one argument of type *template.Template (pointer to template.Template). The function home also returns a single argument of type func(http.ResponseWriter, *http.Request), that is, it returns a function which takes two arguments. This is a common function signature in the "net/http" package.


  return func(w http.ResponseWriter, r *http.Request) {

Our new function home requires us to return a func, so here we define and return one.


  err := layout.Execute(w, nil)
    if err != nil {
      log.Panic(err)
    }
  }
}

We call Execute(w, nil) on our passed in layout which will write the template to the http.ResponseWriter. Ignore the nil for now, we'll use that later to pass in variables. And as always, grab the error and do something useful with it.

We should call the http.ResponseWriter's WriteHeader function with 200 but golang does this for us if we don't.