A golang web app tutorial
I did some work with Google Go recently and had the chance to follow their great tutorial Writing Web Applications. The tutorial is pretty simple: use the Go http library to create a very simple wiki-style site. I like this tutorial a lot because there’s not too much hand-holding, but they do eventually hand you the final code listing. Then the good people at Google give you the tall task of completing the following ‘Other tasks’ without solutions:
- Store templates in tmpl/ and page data in data/.
- Add a handler to make the web root redirect to /view/FrontPage.
- Spruce up the page templates by making them valid HTML and adding some CSS rules.
- Implement inter-page linking by converting instances of [PageName] to \PageName\</a>. (hint: you could use regexp.ReplaceAllFunc to do this)
This is what I’d like to go over. I scoured the web and didn’t have much luck finding solutions to these issues. That would be okay if they were all trivial, but the final step is not straightforward. I’m going to assume you’ve already gone over the tutorial. You can see my repository on Github, and I have included links to the appropriate commits in the code sections of this blog post.
Store templates in tmpl/ and page data in data/
The tutorial originally has the developer store all pages in the project directory. Every time a user made a new wiki page, a new file would creep into the project directory. All HTML templates were also stored in the project directory.
Moving templates is quite trivial. In the global scope:
1 2 |
|
I found moving the page data to data/
was a little trickier, especially if the directory didn’t already exist. You may not have the same issue, but I remedied this by creating the directory if it doesn’t exist. My save
function differences:
1 2 3 4 5 6 7 |
|
Add a handler to make the web root redirect to /view/FrontPage
All we’re going to do is create a simple handler called rootHandler
that redirects to a new page called FrontPage
. We then add it in the main
function. The tutorial had us wrap out handlers in a function call to take some special actions, but that wrapper would mess up our handler in its current form. So I just Redirect
to the view
handler, which will then decide whether to view or create the FrontPage.
1 2 3 4 5 6 7 8 9 10 11 |
|
Spruce up the page templates by making them valid HTML and adding some CSS rules.
I took my old .html
files and put them through a validator. Making them valid only involved adding DOCTYPE
, html
, and head
tags. The head
tag needed meta
, and title
tags and we were valid. I’ve shown view.html
below.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Implement inter-page linking by converting instances of [PageName]
Converting [PageName] to a hyperlink was a bit more complicated than expected. I originally just tried to run the string through ReplaceAllFunc
and replace all instance of [PageName] with an equivalent hyperlink. This does not work because we use Go’s ExecuteTemplate
method to render our template. ExecuteTemplate
escapes any HTML that we give it to prevent us from displaying unwanted HTML. Getting around this was the fun part, because I want the benefit of escaped HTML while still having the ability to substitute my own HTML.
As it turns out, ExecuteTemplate
will not escape variables of the type template.HTML
. So I added another variable onto the Page
struct called DisplayBody
.
1 2 3 4 5 |
|
Next, I create a regular expression to find instances of [PageName] and I put the defintion above the main
method.
1
|
|
In my viewHandler
, I escape Body
and then set DisplayBody
to that escaped string with the links substituted.
1 2 3 4 5 6 7 8 9 |
|
To finish up, I modify the view.html
to show DisplayBody
. I don’t use printf
, because that would turn DisplayBody
back into a string
and ExecuteTemplate
would escape it.
1 2 |
|
And that completes the extra exercises for Google’s Writing Web Applications tutorial. Hopefully one day this helps someone who gets stuck.