diff --git a/doc/effective_go.html b/doc/effective_go.html index f3f8020e64..103cc82495 100644 --- a/doc/effective_go.html +++ b/doc/effective_go.html @@ -2360,6 +2360,137 @@ for try := 0; try < 2; try++ { } +

A web server

+ +

+Let's finish with a complete Go program, a web server. +This one is actually a kind of web re-server. +Google provides a service at +http://chart.apis.google.com +that does automatic formatting of data into charts and graphs. +It's hard to use interactively, though, +because you need to put the data into the URL as a query. +The program here provides a nicer interface to one form of data: given a short piece of text, +it calls on the chart server to produce a QR code, a matrix of boxes that encode the +text. +That image can be grabbed with your cell phone's camera and interpreted as, +for instance, a URL, saving you typing the URL into the phone's tiny keyboard. +

+

+Here's the complete program. +An explanation follows. +

+ +
+package main
+
+import (
+	"flag";
+	"http";
+	"io";
+	"log";
+	"strings";
+	"template";
+)
+
+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)
+
+func main() {
+	flag.Parse();
+	http.Handle("/", http.HandlerFunc(QR));
+	err := http.ListenAndServe(*addr, nil);
+	if err != nil {
+		log.Exit("ListenAndServe:", err);
+	}
+}
+
+func QR(c *http.Conn, req *http.Request) {
+	templ.Execute(req.FormValue("s"), c);
+}
+
+func UrlHtmlFormatter(w io.Writer, v interface{}, fmt string) {
+	template.HtmlEscape(w, strings.Bytes(http.URLEscape(v.(string))));
+}
+
+
+const templateStr = `
+<html>
+<head>
+<title>QR Link Generator</title>
+</head>
+<body>
+{.section @}
+<img src="http://chart.apis.google.com/chart?chs=300x300&cht=qr&choe=UTF-8&chl={@|url+html}"
+/>
+<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>
+`
+
+ +

+The pieces up to main should be easy to follow. +The one flag sets a default HTTP port for our server. The template +variable templ is where the fun happens. It builds an HTML template +that will be executed by the server to display the page; more about +that in a moment. +

+

+The main function parses the flags and, using the mechanism +we talked about above, binds the function QR to the root path +for the server. Then http.ListenAndServe is called to start the +server; it blocks while the server runs. +

+

+QR just receives the request, which contains form data, and +executes the template on the data in the field named s. +

+

+The template package, inspired by json-template, 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 templ.Execute, in this case the +string in the form data. +Within the template text (templateStr), +brace-delimited pieces denote template actions. +The piece from the {.section @} +to {.end} executes with the value of the data item @, +which is a shorthand for “the current item”, in this case the form data. +(When the string is empty, this piece of the template is suppressed.) +

+

+The snippet {@|url+html} says to run the data through the formatter +installed in the formatter map (fmap) +under the name "url+html". +That is the function UrlHtmlFormatter, which sanitizes the string +for safe display on the web page. +

+

+The rest of the template string is just the HTML to show when the page loads. +If this is too quick an explanation, see the documentation +for the template package for a more thorough discussion. +

+

+And there you have it: a useful webserver in a few lines of code plus some +data-driven HTML text. +Go is powerful enough to make a lot happen in a few lines. +

+