How are people handling the use of templates in their Go-based AppEngine applications?
Specifically, I'm looking for a project structure that affords the following:
Potential stumbling blocks are:
Please note that I am not looking for a tutorial/examples of the use of the template package. This is more of an app structure question. That being said, if you have code that solves the above problems, I would love to see it. Thanks in advance.
One of my favorite features of Go is the ability to easily add handlers inside of packages. This greatly simplifies the processes of writing modular code.
For Example:
File Structure
|-- app.yaml |-- app | +-- http.go |-- templates | +-- base.html +-- github.com +-- storeski +-- appengine |-- products | |-- http.go | +-- templates | |-- list.html | +-- detail.html +-- account |-- http.go +-- templates |-- overview.html +-- notifications.html
Each packages has a http.go file that takes ownership of a url prefix. For example the products
package under github.com/storeski/appengine/products
would own any inbound url starting with /products
.
With this modular approach it is beneficial to store the templates within the products
package. If you would like to maintain a consistant base template for the site you can establish a convention where you extend templates/base.html
.
Example
templates/base.html
<!DOCTYPE HTML> <html> <head> <title>{{.Store.Title}}</title> </head> <body> <div id="content"> {{template "content" .}} </div> </body> </html>
github.com/storeski/appengine/products/templates/list.html
{{define "content"}} <h1> Products List </h1> {{end}}
github.com/storeski/appengine/products/http.go
func init() { http.HandleFunc("/products", listHandler) } var listTmpl = template.Must(template.ParseFiles("templates/base.html", "github.com/storeski/appengine/products/templates/list.html")) func listHandler(w http.ResponseWriter, r *http.Request) { tc := make(map[string]interface{}) tc["Store"] = Store tc["Products"] = Products if err := listTmpl.Execute(w, tc); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } }
This approach is very exciting because it makes the sharing of apps/package trivial. If I write a package that handles authentication which takes ownership of the /auth
url. Any developer that, then, adds the package to their product root instantly has all of the functionality. All they have to do is create a base template (templates/base.html
) and direct their users to /auth
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With