Commit b67b72da authored by Andrew Gerrand's avatar Andrew Gerrand

doc/codelab: use new template package

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/4897048
parent 0f801ff8
<h1>Editing {Title}</h1> <h1>Editing {{.Title |html}}</h1>
<form action="/save/{Title}" method="POST"> <form action="/save/{{.Title |html}}" method="POST">
<div><textarea name="body" rows="20" cols="80">{Body|html}</textarea></div> <div><textarea name="body" rows="20" cols="80">{{printf "%s" .Body |html}}</textarea></div>
<div><input type="submit" value="Save"></div> <div><input type="submit" value="Save"></div>
</form> </form>
...@@ -3,9 +3,9 @@ package main ...@@ -3,9 +3,9 @@ package main
import ( import (
"http" "http"
"io/ioutil" "io/ioutil"
"old/template"
"os" "os"
"regexp" "regexp"
"template"
) )
type Page struct { type Page struct {
...@@ -68,7 +68,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) { ...@@ -68,7 +68,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) {
} }
func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) { func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
t, err := template.ParseFile(tmpl+".html", nil) t, err := template.ParseFile(tmpl+".html")
if err != nil { if err != nil {
http.Error(w, err.String(), http.StatusInternalServerError) http.Error(w, err.String(), http.StatusInternalServerError)
return return
......
...@@ -3,8 +3,8 @@ package main ...@@ -3,8 +3,8 @@ package main
import ( import (
"http" "http"
"io/ioutil" "io/ioutil"
"old/template"
"os" "os"
"template"
) )
type Page struct { type Page struct {
...@@ -34,14 +34,14 @@ func editHandler(w http.ResponseWriter, r *http.Request) { ...@@ -34,14 +34,14 @@ func editHandler(w http.ResponseWriter, r *http.Request) {
if err != nil { if err != nil {
p = &Page{Title: title} p = &Page{Title: title}
} }
t, _ := template.ParseFile("edit.html", nil) t, _ := template.ParseFile("edit.html")
t.Execute(w, p) t.Execute(w, p)
} }
func viewHandler(w http.ResponseWriter, r *http.Request) { func viewHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[lenPath:] title := r.URL.Path[lenPath:]
p, _ := loadPage(title) p, _ := loadPage(title)
t, _ := template.ParseFile("view.html", nil) t, _ := template.ParseFile("view.html")
t.Execute(w, p) t.Execute(w, p)
} }
......
...@@ -3,9 +3,9 @@ package main ...@@ -3,9 +3,9 @@ package main
import ( import (
"http" "http"
"io/ioutil" "io/ioutil"
"old/template"
"os" "os"
"regexp" "regexp"
"template"
) )
type Page struct { type Page struct {
...@@ -59,7 +59,8 @@ var templates = make(map[string]*template.Template) ...@@ -59,7 +59,8 @@ var templates = make(map[string]*template.Template)
func init() { func init() {
for _, tmpl := range []string{"edit", "view"} { for _, tmpl := range []string{"edit", "view"} {
templates[tmpl] = template.MustParseFile(tmpl+".html", nil) t := template.Must(template.ParseFile(tmpl+".html"))
templates[tmpl] = t
} }
} }
......
package main package main
import ( import (
"old/template" "template"
"os" "os"
"io/ioutil" "io/ioutil"
) )
func main() { func main() {
b, _ := ioutil.ReadAll(os.Stdin) b, _ := ioutil.ReadAll(os.Stdin)
template.HTMLFormatter(os.Stdout, "", b) template.HTMLEscape(os.Stdout, b)
} }
...@@ -7,7 +7,7 @@ Covered in this codelab: ...@@ -7,7 +7,7 @@ Covered in this codelab:
<ul> <ul>
<li>Creating a data structure with load and save methods</li> <li>Creating a data structure with load and save methods</li>
<li>Using the <code>http</code> package to build web applications <li>Using the <code>http</code> package to build web applications
<li>Using the <code>old/template</code> package to process HTML templates</li> <li>Using the <code>template</code> package to process HTML templates</li>
<li>Using the <code>regexp</code> package to validate user input</li> <li>Using the <code>regexp</code> package to validate user input</li>
<li>Using closures</li> <li>Using closures</li>
</ul> </ul>
...@@ -426,27 +426,27 @@ This function will work fine, but all that hard-coded HTML is ugly. ...@@ -426,27 +426,27 @@ This function will work fine, but all that hard-coded HTML is ugly.
Of course, there is a better way. Of course, there is a better way.
</p> </p>
<h2>The <code>old/template</code> package</h2> <h2>The <code>template</code> package</h2>
<p> <p>
The <code>old/template</code> package is part of the Go standard library. The <code>template</code> package is part of the Go standard library.
(A new template package is coming; this code lab will be updated soon.) (A new template package is coming; this code lab will be updated soon.)
We can We can
use <code>old/template</code> to keep the HTML in a separate file, allowing use <code>template</code> to keep the HTML in a separate file, allowing
us to change the layout of our edit page without modifying the underlying Go us to change the layout of our edit page without modifying the underlying Go
code. code.
</p> </p>
<p> <p>
First, we must add <code>old/template</code> to the list of imports: First, we must add <code>template</code> to the list of imports:
</p> </p>
<pre> <pre>
import ( import (
"http" "http"
"io/ioutil" "io/ioutil"
<b>"old/template"</b>
"os" "os"
<b>"template"</b>
) )
</pre> </pre>
...@@ -456,10 +456,10 @@ Open a new file named <code>edit.html</code>, and add the following lines: ...@@ -456,10 +456,10 @@ Open a new file named <code>edit.html</code>, and add the following lines:
</p> </p>
<pre> <pre>
&lt;h1&gt;Editing {Title}&lt;/h1&gt; &lt;h1&gt;Editing {{.Title |html}}&lt;/h1&gt;
&lt;form action=&#34;/save/{Title}&#34; method=&#34;POST&#34;&gt; &lt;form action=&#34;/save/{{.Title |html}}&#34; method=&#34;POST&#34;&gt;
&lt;div&gt;&lt;textarea name=&#34;body&#34; rows=&#34;20&#34; cols=&#34;80&#34;&gt;{Body|html}&lt;/textarea&gt;&lt;/div&gt; &lt;div&gt;&lt;textarea name=&#34;body&#34; rows=&#34;20&#34; cols=&#34;80&#34;&gt;{{printf &#34;%s&#34; .Body |html}}&lt;/textarea&gt;&lt;/div&gt;
&lt;div&gt;&lt;input type=&#34;submit&#34; value=&#34;Save&#34;&gt;&lt;/div&gt; &lt;div&gt;&lt;input type=&#34;submit&#34; value=&#34;Save&#34;&gt;&lt;/div&gt;
&lt;/form&gt; &lt;/form&gt;
</pre> </pre>
...@@ -476,7 +476,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) { ...@@ -476,7 +476,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) {
if err != nil { if err != nil {
p = &amp;Page{Title: title} p = &amp;Page{Title: title}
} }
t, _ := template.ParseFile(&#34;edit.html&#34;, nil) t, _ := template.ParseFile(&#34;edit.html&#34;)
t.Execute(w, p) t.Execute(w, p)
} }
</pre> </pre>
...@@ -487,19 +487,21 @@ The function <code>template.ParseFile</code> will read the contents of ...@@ -487,19 +487,21 @@ The function <code>template.ParseFile</code> will read the contents of
</p> </p>
<p> <p>
The method <code>t.Execute</code> replaces all occurrences of The method <code>t.Execute</code> executes the template, writing the
<code>{Title}</code> and <code>{Body}</code> with the values of generated HTML to the <code>http.ResponseWriter</code>.
<code>p.Title</code> and <code>p.Body</code>, and writes the resultant The <code>.Title</code> and <code>.Body</code> dotted identifiers refer to
HTML to the <code>http.ResponseWriter</code>. <code>p.Title</code> and <code>p.Body</code>.
</p> </p>
<p> <p>
Note that we've used <code>{Body|html}</code> in the above template. Template directives are enclosed in double curly braces.
The <code>|html</code> part asks the template engine to pass the value The <code>printf "%s" .Body</code> instruction is a function call
<code>Body</code> through the <code>html</code> formatter before outputting it, that outputs <code>.Body</code> as a string instead of a stream of bytes,
which escapes HTML characters (such as replacing <code>&gt;</code> with the same as a call to <code>fmt.Printf</code>.
<code>&amp;gt;</code>). The <code>|html</code> part of each directive pipes the value through the
This will prevent user data from corrupting the form HTML. <code>html</code> formatter before outputting it, which escapes HTML
characters (such as replacing <code>&gt;</code> with <code>&amp;gt;</code>),
preventing user data from corrupting the form HTML.
</p> </p>
<p> <p>
...@@ -513,11 +515,11 @@ While we're working with templates, let's create a template for our ...@@ -513,11 +515,11 @@ While we're working with templates, let's create a template for our
</p> </p>
<pre> <pre>
&lt;h1&gt;{Title}&lt;/h1&gt; &lt;h1&gt;{{.Title |html}}&lt;/h1&gt;
&lt;p&gt;[&lt;a href=&#34;/edit/{Title}&#34;&gt;edit&lt;/a&gt;]&lt;/p&gt; &lt;p&gt;[&lt;a href=&#34;/edit/{{.Title |html}}&#34;&gt;edit&lt;/a&gt;]&lt;/p&gt;
&lt;div&gt;{Body}&lt;/div&gt; &lt;div&gt;{{printf &#34;%s&#34; .Body |html}}&lt;/div&gt;
</pre> </pre>
<p> <p>
...@@ -528,7 +530,7 @@ Modify <code>viewHandler</code> accordingly: ...@@ -528,7 +530,7 @@ Modify <code>viewHandler</code> accordingly:
func viewHandler(w http.ResponseWriter, r *http.Request) { func viewHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[lenPath:] title := r.URL.Path[lenPath:]
p, _ := loadPage(title) p, _ := loadPage(title)
t, _ := template.ParseFile(&#34;view.html&#34;, nil) t, _ := template.ParseFile(&#34;view.html&#34;)
t.Execute(w, p) t.Execute(w, p)
} }
</pre> </pre>
...@@ -708,16 +710,17 @@ var templates = make(map[string]*template.Template) ...@@ -708,16 +710,17 @@ var templates = make(map[string]*template.Template)
<p> <p>
Then we create an <code>init</code> function, which will be called before Then we create an <code>init</code> function, which will be called before
<code>main</code> at program initialization. The function <code>main</code> at program initialization. The function
<code>template.MustParseFile</code> is a convenience wrapper around <code>template.Must</code> is a convenience wrapper that panics when passed a
<code>ParseFile</code> that does not return an error code; instead, it panics non-nil <code>os.Error</code> value, and otherwise returns the
if an error is encountered. A panic is appropriate here; if the templates can't <code>*Template</code> unaltered. A panic is appropriate here; if the templates
be loaded the only sensible thing to do is exit the program. can't be loaded the only sensible thing to do is exit the program.
</p> </p>
<pre> <pre>
func init() { func init() {
for _, tmpl := range []string{&#34;edit&#34;, &#34;view&#34;} { for _, tmpl := range []string{&#34;edit&#34;, &#34;view&#34;} {
templates[tmpl] = template.MustParseFile(tmpl+&#34;.html&#34;, nil) t := template.Must(template.ParseFile(tmpl + &#34;.html&#34;))
templates[tmpl] = t
} }
} }
</pre> </pre>
...@@ -763,10 +766,9 @@ var titleValidator = regexp.MustCompile(&#34;^[a-zA-Z0-9]+$&#34;) ...@@ -763,10 +766,9 @@ var titleValidator = regexp.MustCompile(&#34;^[a-zA-Z0-9]+$&#34;)
<p> <p>
The function <code>regexp.MustCompile</code> will parse and compile the The function <code>regexp.MustCompile</code> will parse and compile the
regular expression, and return a <code>regexp.Regexp</code>. regular expression, and return a <code>regexp.Regexp</code>.
<code>MustCompile</code>, like <code>template.MustParseFile</code>, <code>MustCompile</code> is distinct from <code>Compile</code> in that it will
is distinct from <code>Compile</code> in that it will panic if panic if the expression compilation fails, while <code>Compile</code> returns
the expression compilation fails, while <code>Compile</code> returns an an <code>os.Error</code> as a second parameter.
<code>os.Error</code> as a second parameter.
</p> </p>
<p> <p>
......
...@@ -8,7 +8,7 @@ import ( ...@@ -8,7 +8,7 @@ import (
"go/ast" "go/ast"
"go/token" "go/token"
"log" "log"
"old/template" "template"
"os" "os"
) )
......
<h1>{Title}</h1> <h1>{{.Title |html}}</h1>
<p>[<a href="/edit/{Title}">edit</a>]</p> <p>[<a href="/edit/{{.Title |html}}">edit</a>]</p>
<div>{Body}</div> <div>{{printf "%s" .Body |html}}</div>
...@@ -7,7 +7,7 @@ Covered in this codelab: ...@@ -7,7 +7,7 @@ Covered in this codelab:
<ul> <ul>
<li>Creating a data structure with load and save methods</li> <li>Creating a data structure with load and save methods</li>
<li>Using the <code>http</code> package to build web applications <li>Using the <code>http</code> package to build web applications
<li>Using the <code>old/template</code> package to process HTML templates</li> <li>Using the <code>template</code> package to process HTML templates</li>
<li>Using the <code>regexp</code> package to validate user input</li> <li>Using the <code>regexp</code> package to validate user input</li>
<li>Using closures</li> <li>Using closures</li>
</ul> </ul>
...@@ -366,27 +366,27 @@ This function will work fine, but all that hard-coded HTML is ugly. ...@@ -366,27 +366,27 @@ This function will work fine, but all that hard-coded HTML is ugly.
Of course, there is a better way. Of course, there is a better way.
</p> </p>
<h2>The <code>old/template</code> package</h2> <h2>The <code>template</code> package</h2>
<p> <p>
The <code>old/template</code> package is part of the Go standard library. The <code>template</code> package is part of the Go standard library.
(A new template package is coming; this code lab will be updated soon.) (A new template package is coming; this code lab will be updated soon.)
We can We can
use <code>old/template</code> to keep the HTML in a separate file, allowing use <code>template</code> to keep the HTML in a separate file, allowing
us to change the layout of our edit page without modifying the underlying Go us to change the layout of our edit page without modifying the underlying Go
code. code.
</p> </p>
<p> <p>
First, we must add <code>old/template</code> to the list of imports: First, we must add <code>template</code> to the list of imports:
</p> </p>
<pre> <pre>
import ( import (
"http" "http"
"io/ioutil" "io/ioutil"
<b>"old/template"</b>
"os" "os"
<b>"template"</b>
) )
</pre> </pre>
...@@ -414,19 +414,21 @@ The function <code>template.ParseFile</code> will read the contents of ...@@ -414,19 +414,21 @@ The function <code>template.ParseFile</code> will read the contents of
</p> </p>
<p> <p>
The method <code>t.Execute</code> replaces all occurrences of The method <code>t.Execute</code> executes the template, writing the
<code>{Title}</code> and <code>{Body}</code> with the values of generated HTML to the <code>http.ResponseWriter</code>.
<code>p.Title</code> and <code>p.Body</code>, and writes the resultant The <code>.Title</code> and <code>.Body</code> dotted identifiers refer to
HTML to the <code>http.ResponseWriter</code>. <code>p.Title</code> and <code>p.Body</code>.
</p> </p>
<p> <p>
Note that we've used <code>{Body|html}</code> in the above template. Template directives are enclosed in double curly braces.
The <code>|html</code> part asks the template engine to pass the value The <code>printf "%s" .Body</code> instruction is a function call
<code>Body</code> through the <code>html</code> formatter before outputting it, that outputs <code>.Body</code> as a string instead of a stream of bytes,
which escapes HTML characters (such as replacing <code>&gt;</code> with the same as a call to <code>fmt.Printf</code>.
<code>&amp;gt;</code>). The <code>|html</code> part of each directive pipes the value through the
This will prevent user data from corrupting the form HTML. <code>html</code> formatter before outputting it, which escapes HTML
characters (such as replacing <code>&gt;</code> with <code>&amp;gt;</code>),
preventing user data from corrupting the form HTML.
</p> </p>
<p> <p>
...@@ -572,10 +574,10 @@ our <code>*Template</code> values, keyed by <code>string</code> ...@@ -572,10 +574,10 @@ our <code>*Template</code> values, keyed by <code>string</code>
<p> <p>
Then we create an <code>init</code> function, which will be called before Then we create an <code>init</code> function, which will be called before
<code>main</code> at program initialization. The function <code>main</code> at program initialization. The function
<code>template.MustParseFile</code> is a convenience wrapper around <code>template.Must</code> is a convenience wrapper that panics when passed a
<code>ParseFile</code> that does not return an error code; instead, it panics non-nil <code>os.Error</code> value, and otherwise returns the
if an error is encountered. A panic is appropriate here; if the templates can't <code>*Template</code> unaltered. A panic is appropriate here; if the templates
be loaded the only sensible thing to do is exit the program. can't be loaded the only sensible thing to do is exit the program.
</p> </p>
<pre> <pre>
...@@ -618,10 +620,9 @@ Then we can create a global variable to store our validation regexp: ...@@ -618,10 +620,9 @@ Then we can create a global variable to store our validation regexp:
<p> <p>
The function <code>regexp.MustCompile</code> will parse and compile the The function <code>regexp.MustCompile</code> will parse and compile the
regular expression, and return a <code>regexp.Regexp</code>. regular expression, and return a <code>regexp.Regexp</code>.
<code>MustCompile</code>, like <code>template.MustParseFile</code>, <code>MustCompile</code> is distinct from <code>Compile</code> in that it will
is distinct from <code>Compile</code> in that it will panic if panic if the expression compilation fails, while <code>Compile</code> returns
the expression compilation fails, while <code>Compile</code> returns an an <code>os.Error</code> as a second parameter.
<code>os.Error</code> as a second parameter.
</p> </p>
<p> <p>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment