1
0
mirror of https://github.com/golang/go synced 2024-11-22 02:04:40 -07:00

doc/codelab: use new template package

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/4897048
This commit is contained in:
Andrew Gerrand 2011-08-18 10:38:08 +10:00
parent 0f801ff81e
commit b67b72da43
9 changed files with 77 additions and 73 deletions

View File

@ -1,6 +1,6 @@
<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>

View File

@ -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) {
} }
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

View File

@ -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) {
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)
} }

View File

@ -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)
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
} }
} }

View File

@ -1,12 +1,12 @@
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)
} }

View File

@ -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.
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:
</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) {
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
</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
</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:
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)
<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;)
<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>

View File

@ -8,7 +8,7 @@ import (
"go/ast" "go/ast"
"go/token" "go/token"
"log" "log"
"old/template" "template"
"os" "os"
) )

View File

@ -1,5 +1,5 @@
<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>

View File

@ -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.
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
</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>
<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:
<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>