1
0
mirror of https://github.com/golang/go synced 2024-11-23 20:10:08 -07:00

effective_go: convert to use tmpltohtml.

Also update the big example to the new template system.
There are a number of other examples that should be
extracted; this CL serves as an introduction to the
approach.

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/4923043
This commit is contained in:
Rob Pike 2011-08-21 09:46:19 +10:00
parent 1446ffc265
commit d1a3edaee7
6 changed files with 3069 additions and 48 deletions

View File

@ -8,4 +8,11 @@ TARG=tmpltohtml
GOFILES=\
tmpltohtml.go\
go_tutorial.html: go_tutorial.tmpl tmpltohtml
makehtml go_tutorial.tmpl
effective_go.html: effective_go.tmpl tmpltohtml
makehtml effective_go.tmpl
include ../src/Make.cmd

View File

@ -793,7 +793,7 @@ func ReadFull(r Reader, buf []byte) (n int, err os.Error) {
var nr int
nr, err = r.Read(buf)
n += nr
buf = buf[nr:len(buf)]
buf = buf[nr:]
}
return
}
@ -954,8 +954,9 @@ In Go terminology, it returns a pointer to a newly allocated zero value of type
</p>
<p>
Since the memory returned by <code>new</code> is zeroed, it's helpful to arrange that the
zeroed object can be used without further initialization. This means a user of
Since the memory returned by <code>new</code> is zeroed, it's helpful to arrange
when designing your data structures that the
zero value of each type can be used without further initialization. This means a user of
the data structure can create one with <code>new</code> and get right to
work.
For example, the documentation for <code>bytes.Buffer</code> states that
@ -1075,8 +1076,9 @@ m := map[int]string{Enone: "no error", Eio: "Eio", Einval: "invalid argument"}
Back to allocation.
The built-in function <code>make(T, </code><i>args</i><code>)</code> serves
a purpose different from <code>new(T)</code>.
It creates slices, maps, and channels only, and it returns an initialized (not zero)
value of type <code>T</code>, not <code>*T</code>.
It creates slices, maps, and channels only, and it returns an <em>initialized</em>
(not <em>zeroed</em>)
value of type <code>T</code> (not <code>*T</code>).
The reason for the distinction
is that these three types are, under the covers, references to data structures that
must be initialized before use.
@ -2917,66 +2919,55 @@ for instance, a URL, saving you typing the URL into the phone's tiny keyboard.
Here's the complete program.
An explanation follows.
</p>
<pre>
package main
<pre><!--{{code "progs/eff_qr.go"}}
-->package main
import (
"flag"
"http"
"io"
"log"
"old/template" // New template package coming soon...
&#34;flag&#34;
&#34;http&#34;
&#34;log&#34;
&#34;template&#34;
)
var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
var fmap = template.FormatterMap{
"html": template.HTMLFormatter,
"url+html": UrlHtmlFormatter,
}
var templ = template.MustParse(templateStr, fmap)
var addr = flag.String(&#34;addr&#34;, &#34;:1718&#34;, &#34;http service address&#34;) // Q=17, R=18
var templ = template.Must(template.New(&#34;qr&#34;).Parse(templateStr))
func main() {
flag.Parse()
http.Handle("/", http.HandlerFunc(QR))
http.Handle(&#34;/&#34;, http.HandlerFunc(QR))
err := http.ListenAndServe(*addr, nil)
if err != nil {
log.Fatal("ListenAndServe:", err)
log.Fatal(&#34;ListenAndServe:&#34;, err)
}
}
func QR(w http.ResponseWriter, req *http.Request) {
templ.Execute(w, req.FormValue("s"))
templ.Execute(w, req.FormValue(&#34;s&#34;))
}
func UrlHtmlFormatter(w io.Writer, fmt string, v ...interface{}) {
template.HTMLEscape(w, []byte(http.URLEscape(v[0].(string))))
}
const templateStr = `
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;QR Link Generator&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
{.section @}
&lt;img src="http://chart.apis.google.com/chart?chs=300x300&amp;cht=qr&amp;choe=UTF-8&amp;chl={@|url+html}"
{{if .}}
&lt;img src=&#34;http://chart.apis.google.com/chart?chs=300x300&amp;amp;cht=qr&amp;amp;choe=UTF-8&amp;amp;chl={{urlquery .}}&#34;
/&gt;
&lt;br&gt;
{@|html}
{{html .}}
&lt;br&gt;
&lt;br&gt;
{.end}
&lt;form action="/" name=f method="GET"&gt;&lt;input maxLength=1024 size=70
name=s value="" title="Text to QR Encode"&gt;&lt;input type=submit
value="Show QR" name=qr&gt;
{{end}}
&lt;form action=&#34;/&#34; name=f method=&#34;GET&#34;&gt;&lt;input maxLength=1024 size=70
name=s value=&#34;&#34; title=&#34;Text to QR Encode&#34;&gt;&lt;input type=submit
value=&#34;Show QR&#34; name=qr&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
`
</pre>
<p>
The pieces up to <code>main</code> should be easy to follow.
The one flag sets a default HTTP port for our server. The template
@ -2995,25 +2986,20 @@ server; it blocks while the server runs.
executes the template on the data in the form value named <code>s</code>.
</p>
<p>
The template package, inspired by <a
href="http://code.google.com/p/json-template">json-template</a>, is
powerful;
The template package is powerful;
this program just touches on its capabilities.
In essence, it rewrites a piece of text on the fly by substituting elements derived
from data items passed to <code>templ.Execute</code>, in this case the
form value.
Within the template text (<code>templateStr</code>),
brace-delimited pieces denote template actions.
The piece from the <code>{.section @}</code>
to <code>{.end}</code> executes with the value of the data item <code>@</code>,
which is a shorthand for &ldquo;the current item&rdquo;, which is the form value.
(When the string is empty, this piece of the template is suppressed.)
double-brace-delimited pieces denote template actions.
The piece from the <code></code> executes only if the value of the current data item, called <code>.</code>,
is non-empty.
That is, when the string is empty, this piece of the template is suppressed.
</p>
<p>
The snippet <code>{@|url+html}</code> says to run the data through the formatter
installed in the formatter map (<code>fmap</code>)
under the name <code>"url+html"</code>.
That is the function <code>UrlHtmlFormatter</code>, which sanitizes the string
The snippet <code>0</code> says to process the data with the function
<code>urlquery</code>, which sanitizes the query string
for safe display on the web page.
</p>
<p>

2980
doc/effective_go.tmpl Normal file

File diff suppressed because it is too large Load Diff

View File

@ -14,4 +14,4 @@ then
exit 1
fi
make && ./tmpltohtml $TMPL > $HTML
make tmpltohtml && ./tmpltohtml $TMPL > $HTML

47
doc/progs/eff_qr.go Normal file
View File

@ -0,0 +1,47 @@
package main
import (
"flag"
"http"
"log"
"template"
)
var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
var templ = template.Must(template.New("qr").Parse(templateStr))
func main() {
flag.Parse()
http.Handle("/", http.HandlerFunc(QR))
err := http.ListenAndServe(*addr, nil)
if err != nil {
log.Fatal("ListenAndServe:", err)
}
}
func QR(w http.ResponseWriter, req *http.Request) {
templ.Execute(w, req.FormValue("s"))
}
const templateStr = `
<html>
<head>
<title>QR Link Generator</title>
</head>
<body>
{{if .}}
<img src="http://chart.apis.google.com/chart?chs=300x300&amp;cht=qr&amp;choe=UTF-8&amp;chl={{urlquery .}}"
/>
<br>
{{html .}}
<br>
<br>
{{end}}
<form action="/" name=f method="GET"><input maxLength=1024 size=70
name=s value="" title="Text to QR Encode"><input type=submit
value="Show QR" name=qr>
</form>
</body>
</html>
`

View File

@ -35,6 +35,7 @@ for i in \
sieve1.go \
server1.go \
strings.go \
eff_qr.go \
; do
$GC $i
done