Home | History | Annotate | Download | only in wiki
      1 <!--{
      2 	"Title": "Writing Web Applications",
      3 	"Template": true
      4 }-->
      5 
      6 <h2>Introduction</h2>
      7 
      8 <p>
      9 Covered in this tutorial:
     10 </p>
     11 <ul>
     12 <li>Creating a data structure with load and save methods</li>
     13 <li>Using the <code>net/http</code> package to build web applications
     14 <li>Using the <code>html/template</code> package to process HTML templates</li>
     15 <li>Using the <code>regexp</code> package to validate user input</li>
     16 <li>Using closures</li>
     17 </ul>
     18 
     19 <p>
     20 Assumed knowledge:
     21 </p>
     22 <ul>
     23 <li>Programming experience</li>
     24 <li>Understanding of basic web technologies (HTTP, HTML)</li>
     25 <li>Some UNIX/DOS command-line knowledge</li>
     26 </ul>
     27 
     28 <h2>Getting Started</h2>
     29 
     30 <p>
     31 At present, you need to have a FreeBSD, Linux, OS X, or Windows machine to run Go.
     32 We will use <code>$</code> to represent the command prompt.
     33 </p>
     34 
     35 <p>
     36 Install Go (see the <a href="/doc/install">Installation Instructions</a>).
     37 </p>
     38 
     39 <p>
     40 Make a new directory for this tutorial inside your <code>GOPATH</code> and cd to it:
     41 </p>
     42 
     43 <pre>
     44 $ mkdir gowiki
     45 $ cd gowiki
     46 </pre>
     47 
     48 <p>
     49 Create a file named <code>wiki.go</code>, open it in your favorite editor, and
     50 add the following lines:
     51 </p>
     52 
     53 <pre>
     54 package main
     55 
     56 import (
     57 	"fmt"
     58 	"io/ioutil"
     59 )
     60 </pre>
     61 
     62 <p>
     63 We import the <code>fmt</code> and <code>ioutil</code> packages from the Go
     64 standard library. Later, as we implement additional functionality, we will
     65 add more packages to this <code>import</code> declaration.
     66 </p>
     67 
     68 <h2>Data Structures</h2>
     69 
     70 <p>
     71 Let's start by defining the data structures. A wiki consists of a series of
     72 interconnected pages, each of which has a title and a body (the page content).
     73 Here, we define <code>Page</code> as a struct with two fields representing
     74 the title and body.
     75 </p>
     76 
     77 {{code "doc/articles/wiki/part1.go" `/^type Page/` `/}/`}}
     78 
     79 <p>
     80 The type <code>[]byte</code> means "a <code>byte</code> slice".
     81 (See <a href="/doc/articles/slices_usage_and_internals.html">Slices: usage and
     82 internals</a> for more on slices.)
     83 The <code>Body</code> element is a <code>[]byte</code> rather than
     84 <code>string</code> because that is the type expected by the <code>io</code>
     85 libraries we will use, as you'll see below.
     86 </p>
     87 
     88 <p>
     89 The <code>Page</code> struct describes how page data will be stored in memory.
     90 But what about persistent storage? We can address that by creating a
     91 <code>save</code> method on <code>Page</code>:
     92 </p>
     93 
     94 {{code "doc/articles/wiki/part1.go" `/^func.*Page.*save/` `/}/`}}
     95 
     96 <p>
     97 This method's signature reads: "This is a method named <code>save</code> that
     98 takes as its receiver <code>p</code>, a pointer to <code>Page</code> . It takes
     99 no parameters, and returns a value of type <code>error</code>."
    100 </p>
    101 
    102 <p>
    103 This method will save the <code>Page</code>'s <code>Body</code> to a text
    104 file. For simplicity, we will use the <code>Title</code> as the file name.
    105 </p>
    106 
    107 <p>
    108 The <code>save</code> method returns an <code>error</code> value because
    109 that is the return type of <code>WriteFile</code> (a standard library function
    110 that writes a byte slice to a file).  The <code>save</code> method returns the
    111 error value, to let the application handle it should anything go wrong while
    112 writing the file.  If all goes well, <code>Page.save()</code> will return
    113 <code>nil</code> (the zero-value for pointers, interfaces, and some other
    114 types).
    115 </p>
    116 
    117 <p>
    118 The octal integer literal <code>0600</code>, passed as the third parameter to
    119 <code>WriteFile</code>, indicates that the file should be created with
    120 read-write permissions for the current user only. (See the Unix man page
    121 <code>open(2)</code> for details.)
    122 </p>
    123 
    124 <p>
    125 In addition to saving pages, we will want to load pages, too:
    126 </p>
    127 
    128 {{code "doc/articles/wiki/part1-noerror.go" `/^func loadPage/` `/^}/`}}
    129 
    130 <p>
    131 The function <code>loadPage</code> constructs the file name from the title
    132 parameter, reads the file's contents into a new variable <code>body</code>, and
    133 returns a pointer to a <code>Page</code> literal constructed with the proper
    134 title and body values.
    135 </p>
    136 
    137 <p>
    138 Functions can return multiple values. The standard library function
    139 <code>io.ReadFile</code> returns <code>[]byte</code> and <code>error</code>.
    140 In <code>loadPage</code>, error isn't being handled yet; the "blank identifier"
    141 represented by the underscore (<code>_</code>) symbol is used to throw away the
    142 error return value (in essence, assigning the value to nothing).
    143 </p>
    144 
    145 <p>
    146 But what happens if <code>ReadFile</code> encounters an error?  For example,
    147 the file might not exist. We should not ignore such errors.  Let's modify the
    148 function to return <code>*Page</code> and <code>error</code>.
    149 </p>
    150 
    151 {{code "doc/articles/wiki/part1.go" `/^func loadPage/` `/^}/`}}
    152 
    153 <p>
    154 Callers of this function can now check the second parameter; if it is
    155 <code>nil</code> then it has successfully loaded a Page. If not, it will be an
    156 <code>error</code> that can be handled by the caller (see the
    157 <a href="/ref/spec#Errors">language specification</a> for details).
    158 </p>
    159 
    160 <p>
    161 At this point we have a simple data structure and the ability to save to and
    162 load from a file. Let's write a <code>main</code> function to test what we've
    163 written:
    164 </p>
    165 
    166 {{code "doc/articles/wiki/part1.go" `/^func main/` `/^}/`}}
    167 
    168 <p>
    169 After compiling and executing this code, a file named <code>TestPage.txt</code>
    170 would be created, containing the contents of <code>p1</code>. The file would
    171 then be read into the struct <code>p2</code>, and its <code>Body</code> element
    172 printed to the screen.
    173 </p>
    174 
    175 <p>
    176 You can compile and run the program like this:
    177 </p>
    178 
    179 <pre>
    180 $ go build wiki.go
    181 $ ./wiki
    182 This is a sample Page.
    183 </pre>
    184 
    185 <p>
    186 (If you're using Windows you must type "<code>wiki</code>" without the
    187 "<code>./</code>" to run the program.)
    188 </p>
    189 
    190 <p>
    191 <a href="part1.go">Click here to view the code we've written so far.</a>
    192 </p>
    193 
    194 <h2>Introducing the <code>net/http</code> package (an interlude)</h2>
    195 
    196 <p>
    197 Here's a full working example of a simple web server:
    198 </p>
    199 
    200 {{code "doc/articles/wiki/http-sample.go"}}
    201 
    202 <p>
    203 The <code>main</code> function begins with a call to
    204 <code>http.HandleFunc</code>, which tells the <code>http</code> package to
    205 handle all requests to the web root (<code>"/"</code>) with
    206 <code>handler</code>.
    207 </p>
    208 
    209 <p>
    210 It then calls <code>http.ListenAndServe</code>, specifying that it should
    211 listen on port 8080 on any interface (<code>":8080"</code>). (Don't
    212 worry about its second parameter, <code>nil</code>, for now.)
    213 This function will block until the program is terminated.
    214 </p>
    215 
    216 <p>
    217 <code>ListenAndServe</code> always returns an error, since it only returns when an
    218 unexpected error occurs.
    219 In order to log that error we wrap the function call with <code>log.Fatal</code>.
    220 </p>
    221 
    222 <p>
    223 The function <code>handler</code> is of the type <code>http.HandlerFunc</code>.
    224 It takes an <code>http.ResponseWriter</code> and an <code>http.Request</code> as
    225 its arguments.
    226 </p>
    227 
    228 <p>
    229 An <code>http.ResponseWriter</code> value assembles the HTTP server's response; by writing
    230 to it, we send data to the HTTP client.
    231 </p>
    232 
    233 <p>
    234 An <code>http.Request</code> is a data structure that represents the client
    235 HTTP request. <code>r.URL.Path</code> is the path component
    236 of the request URL. The trailing <code>[1:]</code> means
    237 "create a sub-slice of <code>Path</code> from the 1st character to the end."
    238 This drops the leading "/" from the path name.
    239 </p>
    240 
    241 <p>
    242 If you run this program and access the URL:
    243 </p>
    244 <pre>http://localhost:8080/monkeys</pre>
    245 <p>
    246 the program would present a page containing:
    247 </p>
    248 <pre>Hi there, I love monkeys!</pre>
    249 
    250 <h2>Using <code>net/http</code> to serve wiki pages</h2>
    251 
    252 <p>
    253 To use the <code>net/http</code> package, it must be imported:
    254 </p>
    255 
    256 <pre>
    257 import (
    258 	"fmt"
    259 	"io/ioutil"
    260 	<b>"net/http"</b>
    261 )
    262 </pre>
    263 
    264 <p>
    265 Let's create a handler, <code>viewHandler</code> that will allow users to
    266 view a wiki page. It will handle URLs prefixed with "/view/".
    267 </p>
    268 
    269 {{code "doc/articles/wiki/part2.go" `/^func viewHandler/` `/^}/`}}
    270 
    271 <p>
    272 First, this function extracts the page title from <code>r.URL.Path</code>,
    273 the path component of the request URL.
    274 The <code>Path</code> is re-sliced with <code>[len("/view/"):]</code> to drop
    275 the leading <code>"/view/"</code> component of the request path.
    276 This is because the path will invariably begin with <code>"/view/"</code>,
    277 which is not part of the page's title.
    278 </p>
    279 
    280 <p>
    281 The function then loads the page data, formats the page with a string of simple
    282 HTML, and writes it to <code>w</code>, the <code>http.ResponseWriter</code>.
    283 </p>
    284 
    285 <p>
    286 Again, note the use of <code>_</code> to ignore the <code>error</code>
    287 return value from <code>loadPage</code>. This is done here for simplicity
    288 and generally considered bad practice. We will attend to this later.
    289 </p>
    290 
    291 <p>
    292 To use this handler, we rewrite our <code>main</code> function to
    293 initialize <code>http</code> using the <code>viewHandler</code> to handle
    294 any requests under the path <code>/view/</code>.
    295 </p>
    296 
    297 {{code "doc/articles/wiki/part2.go" `/^func main/` `/^}/`}}
    298 
    299 <p>
    300 <a href="part2.go">Click here to view the code we've written so far.</a>
    301 </p>
    302 
    303 <p>
    304 Let's create some page data (as <code>test.txt</code>), compile our code, and
    305 try serving a wiki page.
    306 </p>
    307 
    308 <p>
    309 Open <code>test.txt</code> file in your editor, and save the string "Hello world" (without quotes)
    310 in it.
    311 </p>
    312 
    313 <pre>
    314 $ go build wiki.go
    315 $ ./wiki
    316 </pre>
    317 
    318 <p>
    319 (If you're using Windows you must type "<code>wiki</code>" without the
    320 "<code>./</code>" to run the program.)
    321 </p>
    322 
    323 <p>
    324 With this web server running, a visit to <code><a
    325 href="http://localhost:8080/view/test">http://localhost:8080/view/test</a></code>
    326 should show a page titled "test" containing the words "Hello world".
    327 </p>
    328 
    329 <h2>Editing Pages</h2>
    330 
    331 <p>
    332 A wiki is not a wiki without the ability to edit pages. Let's create two new
    333 handlers: one named <code>editHandler</code> to display an 'edit page' form,
    334 and the other named <code>saveHandler</code> to save the data entered via the
    335 form.
    336 </p>
    337 
    338 <p>
    339 First, we add them to <code>main()</code>:
    340 </p>
    341 
    342 {{code "doc/articles/wiki/final-noclosure.go" `/^func main/` `/^}/`}}
    343 
    344 <p>
    345 The function <code>editHandler</code> loads the page
    346 (or, if it doesn't exist, create an empty <code>Page</code> struct),
    347 and displays an HTML form.
    348 </p>
    349 
    350 {{code "doc/articles/wiki/notemplate.go" `/^func editHandler/` `/^}/`}}
    351 
    352 <p>
    353 This function will work fine, but all that hard-coded HTML is ugly.
    354 Of course, there is a better way.
    355 </p>
    356 
    357 <h2>The <code>html/template</code> package</h2>
    358 
    359 <p>
    360 The <code>html/template</code> package is part of the Go standard library.
    361 We can use <code>html/template</code> to keep the HTML in a separate file,
    362 allowing us to change the layout of our edit page without modifying the
    363 underlying Go code.
    364 </p>
    365 
    366 <p>
    367 First, we must add <code>html/template</code> to the list of imports. We
    368 also won't be using <code>fmt</code> anymore, so we have to remove that.
    369 </p>
    370 
    371 <pre>
    372 import (
    373 	<b>"html/template"</b>
    374 	"io/ioutil"
    375 	"net/http"
    376 )
    377 </pre>
    378 
    379 <p>
    380 Let's create a template file containing the HTML form.
    381 Open a new file named <code>edit.html</code>, and add the following lines:
    382 </p>
    383 
    384 {{code "doc/articles/wiki/edit.html"}}
    385 
    386 <p>
    387 Modify <code>editHandler</code> to use the template, instead of the hard-coded
    388 HTML:
    389 </p>
    390 
    391 {{code "doc/articles/wiki/final-noerror.go" `/^func editHandler/` `/^}/`}}
    392 
    393 <p>
    394 The function <code>template.ParseFiles</code> will read the contents of
    395 <code>edit.html</code> and return a <code>*template.Template</code>.
    396 </p>
    397 
    398 <p>
    399 The method <code>t.Execute</code> executes the template, writing the
    400 generated HTML to the <code>http.ResponseWriter</code>.
    401 The <code>.Title</code> and <code>.Body</code> dotted identifiers refer to
    402 <code>p.Title</code> and <code>p.Body</code>.
    403 </p>
    404 
    405 <p>
    406 Template directives are enclosed in double curly braces.
    407 The <code>printf "%s" .Body</code> instruction is a function call
    408 that outputs <code>.Body</code> as a string instead of a stream of bytes,
    409 the same as a call to <code>fmt.Printf</code>.
    410 The <code>html/template</code> package helps guarantee that only safe and
    411 correct-looking HTML is generated by template actions. For instance, it
    412 automatically escapes any greater than sign (<code>&gt;</code>), replacing it
    413 with <code>&amp;gt;</code>, to make sure user data does not corrupt the form
    414 HTML.
    415 </p>
    416 
    417 <p>
    418 Since we're working with templates now, let's create a template for our
    419 <code>viewHandler</code> called <code>view.html</code>:
    420 </p>
    421 
    422 {{code "doc/articles/wiki/view.html"}}
    423 
    424 <p>
    425 Modify <code>viewHandler</code> accordingly:
    426 </p>
    427 
    428 {{code "doc/articles/wiki/final-noerror.go" `/^func viewHandler/` `/^}/`}}
    429 
    430 <p>
    431 Notice that we've used almost exactly the same templating code in both
    432 handlers. Let's remove this duplication by moving the templating code
    433 to its own function:
    434 </p>
    435 
    436 {{code "doc/articles/wiki/final-template.go" `/^func renderTemplate/` `/^}/`}}
    437 
    438 <p>
    439 And modify the handlers to use that function:
    440 </p>
    441 
    442 {{code "doc/articles/wiki/final-template.go" `/^func viewHandler/` `/^}/`}}
    443 {{code "doc/articles/wiki/final-template.go" `/^func editHandler/` `/^}/`}}
    444 
    445 <p>
    446 If we comment out the registration of our unimplemented save handler in
    447 <code>main</code>, we can once again build and test our program.
    448 <a href="part3.go">Click here to view the code we've written so far.</a>
    449 </p>
    450 
    451 <h2>Handling non-existent pages</h2>
    452 
    453 <p>
    454 What if you visit <a href="http://localhost:8080/view/APageThatDoesntExist">
    455 <code>/view/APageThatDoesntExist</code></a>? You'll see a page containing
    456 HTML. This is because it ignores the error return value from
    457 <code>loadPage</code> and continues to try and fill out the template
    458 with no data. Instead, if the requested Page doesn't exist, it should
    459 redirect the client to the edit Page so the content may be created:
    460 </p>
    461 
    462 {{code "doc/articles/wiki/part3-errorhandling.go" `/^func viewHandler/` `/^}/`}}
    463 
    464 <p>
    465 The <code>http.Redirect</code> function adds an HTTP status code of
    466 <code>http.StatusFound</code> (302) and a <code>Location</code>
    467 header to the HTTP response.
    468 </p>
    469 
    470 <h2>Saving Pages</h2>
    471 
    472 <p>
    473 The function <code>saveHandler</code> will handle the submission of forms
    474 located on the edit pages. After uncommenting the related line in
    475 <code>main</code>, let's implement the handler:
    476 </p>
    477 
    478 {{code "doc/articles/wiki/final-template.go" `/^func saveHandler/` `/^}/`}}
    479 
    480 <p>
    481 The page title (provided in the URL) and the form's only field,
    482 <code>Body</code>, are stored in a new <code>Page</code>.
    483 The <code>save()</code> method is then called to write the data to a file,
    484 and the client is redirected to the <code>/view/</code> page.
    485 </p>
    486 
    487 <p>
    488 The value returned by <code>FormValue</code> is of type <code>string</code>.
    489 We must convert that value to <code>[]byte</code> before it will fit into
    490 the <code>Page</code> struct. We use <code>[]byte(body)</code> to perform
    491 the conversion.
    492 </p>
    493 
    494 <h2>Error handling</h2>
    495 
    496 <p>
    497 There are several places in our program where errors are being ignored.  This
    498 is bad practice, not least because when an error does occur the program will
    499 have unintended behavior. A better solution is to handle the errors and return
    500 an error message to the user. That way if something does go wrong, the server
    501 will function exactly how we want and the user can be notified.
    502 </p>
    503 
    504 <p>
    505 First, let's handle the errors in <code>renderTemplate</code>:
    506 </p>
    507 
    508 {{code "doc/articles/wiki/final-parsetemplate.go" `/^func renderTemplate/` `/^}/`}}
    509 
    510 <p>
    511 The <code>http.Error</code> function sends a specified HTTP response code
    512 (in this case "Internal Server Error") and error message.
    513 Already the decision to put this in a separate function is paying off.
    514 </p>
    515 
    516 <p>
    517 Now let's fix up <code>saveHandler</code>:
    518 </p>
    519 
    520 {{code "doc/articles/wiki/part3-errorhandling.go" `/^func saveHandler/` `/^}/`}}
    521 
    522 <p>
    523 Any errors that occur during <code>p.save()</code> will be reported
    524 to the user.
    525 </p>
    526 
    527 <h2>Template caching</h2>
    528 
    529 <p>
    530 There is an inefficiency in this code: <code>renderTemplate</code> calls
    531 <code>ParseFiles</code> every time a page is rendered.
    532 A better approach would be to call <code>ParseFiles</code> once at program
    533 initialization, parsing all templates into a single <code>*Template</code>.
    534 Then we can use the
    535 <a href="/pkg/html/template/#Template.ExecuteTemplate"><code>ExecuteTemplate</code></a>
    536 method to render a specific template.
    537 </p>
    538 
    539 <p>
    540 First we create a global variable named <code>templates</code>, and initialize
    541 it with <code>ParseFiles</code>.
    542 </p>
    543 
    544 {{code "doc/articles/wiki/final.go" `/var templates/`}}
    545 
    546 <p>
    547 The function <code>template.Must</code> is a convenience wrapper that panics
    548 when passed a non-nil <code>error</code> value, and otherwise returns the
    549 <code>*Template</code> unaltered. A panic is appropriate here; if the templates
    550 can't be loaded the only sensible thing to do is exit the program.
    551 </p>
    552 
    553 <p>
    554 The <code>ParseFiles</code> function takes any number of string arguments that
    555 identify our template files, and parses those files into templates that are
    556 named after the base file name. If we were to add more templates to our
    557 program, we would add their names to the <code>ParseFiles</code> call's
    558 arguments.
    559 </p>
    560 
    561 <p>
    562 We then modify the <code>renderTemplate</code> function to call the
    563 <code>templates.ExecuteTemplate</code> method with the name of the appropriate
    564 template:
    565 </p>
    566 
    567 {{code "doc/articles/wiki/final.go" `/func renderTemplate/` `/^}/`}}
    568 
    569 <p>
    570 Note that the template name is the template file name, so we must
    571 append <code>".html"</code> to the <code>tmpl</code> argument.
    572 </p>
    573 
    574 <h2>Validation</h2>
    575 
    576 <p>
    577 As you may have observed, this program has a serious security flaw: a user
    578 can supply an arbitrary path to be read/written on the server. To mitigate
    579 this, we can write a function to validate the title with a regular expression.
    580 </p>
    581 
    582 <p>
    583 First, add <code>"regexp"</code> to the <code>import</code> list.
    584 Then we can create a global variable to store our validation 
    585 expression:
    586 </p>
    587 
    588 {{code "doc/articles/wiki/final-noclosure.go" `/^var validPath/`}}
    589 
    590 <p>
    591 The function <code>regexp.MustCompile</code> will parse and compile the
    592 regular expression, and return a <code>regexp.Regexp</code>.
    593 <code>MustCompile</code> is distinct from <code>Compile</code> in that it will
    594 panic if the expression compilation fails, while <code>Compile</code> returns
    595 an <code>error</code> as a second parameter.
    596 </p>
    597 
    598 <p>
    599 Now, let's write a function that uses the <code>validPath</code>
    600 expression to validate path and extract the page title:
    601 </p>
    602 
    603 {{code "doc/articles/wiki/final-noclosure.go" `/func getTitle/` `/^}/`}}
    604 
    605 <p>
    606 If the title is valid, it will be returned along with a <code>nil</code>
    607 error value. If the title is invalid, the function will write a
    608 "404 Not Found" error to the HTTP connection, and return an error to the
    609 handler. To create a new error, we have to import the <code>errors</code>
    610 package.
    611 </p>
    612 
    613 <p>
    614 Let's put a call to <code>getTitle</code> in each of the handlers:
    615 </p>
    616 
    617 {{code "doc/articles/wiki/final-noclosure.go" `/^func viewHandler/` `/^}/`}}
    618 {{code "doc/articles/wiki/final-noclosure.go" `/^func editHandler/` `/^}/`}}
    619 {{code "doc/articles/wiki/final-noclosure.go" `/^func saveHandler/` `/^}/`}}
    620 
    621 <h2>Introducing Function Literals and Closures</h2>
    622 
    623 <p>
    624 Catching the error condition in each handler introduces a lot of repeated code.
    625 What if we could wrap each of the handlers in a function that does this
    626 validation and error checking? Go's
    627 <a href="/ref/spec#Function_literals">function
    628 literals</a> provide a powerful means of abstracting functionality
    629 that can help us here.
    630 </p>
    631 
    632 <p>
    633 First, we re-write the function definition of each of the handlers to accept
    634 a title string:
    635 </p>
    636 
    637 <pre>
    638 func viewHandler(w http.ResponseWriter, r *http.Request, title string)
    639 func editHandler(w http.ResponseWriter, r *http.Request, title string)
    640 func saveHandler(w http.ResponseWriter, r *http.Request, title string)
    641 </pre>
    642 
    643 <p>
    644 Now let's define a wrapper function that <i>takes a function of the above
    645 type</i>, and returns a function of type <code>http.HandlerFunc</code>
    646 (suitable to be passed to the function <code>http.HandleFunc</code>):
    647 </p>
    648 
    649 <pre>
    650 func makeHandler(fn func (http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
    651 	return func(w http.ResponseWriter, r *http.Request) {
    652 		// Here we will extract the page title from the Request,
    653 		// and call the provided handler 'fn'
    654 	}
    655 }
    656 </pre>
    657 
    658 <p>
    659 The returned function is called a closure because it encloses values defined
    660 outside of it. In this case, the variable <code>fn</code> (the single argument
    661 to <code>makeHandler</code>) is enclosed by the closure. The variable
    662 <code>fn</code> will be one of our save, edit, or view handlers.
    663 </p>
    664 
    665 <p>
    666 Now we can take the code from <code>getTitle</code> and use it here
    667 (with some minor modifications):
    668 </p>
    669 
    670 {{code "doc/articles/wiki/final.go" `/func makeHandler/` `/^}/`}}
    671 
    672 <p>
    673 The closure returned by <code>makeHandler</code> is a function that takes
    674 an <code>http.ResponseWriter</code> and <code>http.Request</code> (in other
    675 words, an <code>http.HandlerFunc</code>).
    676 The closure extracts the <code>title</code> from the request path, and
    677 validates it with the <code>TitleValidator</code> regexp. If the
    678 <code>title</code> is invalid, an error will be written to the
    679 <code>ResponseWriter</code> using the <code>http.NotFound</code> function.
    680 If the <code>title</code> is valid, the enclosed handler function
    681 <code>fn</code> will be called with the <code>ResponseWriter</code>,
    682 <code>Request</code>, and <code>title</code> as arguments.
    683 </p>
    684 
    685 <p>
    686 Now we can wrap the handler functions with <code>makeHandler</code> in
    687 <code>main</code>, before they are registered with the <code>http</code>
    688 package:
    689 </p>
    690 
    691 {{code "doc/articles/wiki/final.go" `/func main/` `/^}/`}}
    692 
    693 <p>
    694 Finally we remove the calls to <code>getTitle</code> from the handler functions,
    695 making them much simpler:
    696 </p>
    697 
    698 {{code "doc/articles/wiki/final.go" `/^func viewHandler/` `/^}/`}}
    699 {{code "doc/articles/wiki/final.go" `/^func editHandler/` `/^}/`}}
    700 {{code "doc/articles/wiki/final.go" `/^func saveHandler/` `/^}/`}}
    701 
    702 <h2>Try it out!</h2>
    703 
    704 <p>
    705 <a href="final.go">Click here to view the final code listing.</a>
    706 </p>
    707 
    708 <p>
    709 Recompile the code, and run the app:
    710 </p>
    711 
    712 <pre>
    713 $ go build wiki.go
    714 $ ./wiki
    715 </pre>
    716 
    717 <p>
    718 Visiting <a href="http://localhost:8080/view/ANewPage">http://localhost:8080/view/ANewPage</a>
    719 should present you with the page edit form. You should then be able to
    720 enter some text, click 'Save', and be redirected to the newly created page.
    721 </p>
    722 
    723 <h2>Other tasks</h2>
    724 
    725 <p>
    726 Here are some simple tasks you might want to tackle on your own:
    727 </p>
    728 
    729 <ul>
    730 <li>Store templates in <code>tmpl/</code> and page data in <code>data/</code>.
    731 <li>Add a handler to make the web root redirect to
    732 	<code>/view/FrontPage</code>.</li>
    733 <li>Spruce up the page templates by making them valid HTML and adding some
    734 	CSS rules.</li>
    735 <li>Implement inter-page linking by converting instances of
    736 	<code>[PageName]</code> to <br>
    737 	<code>&lt;a href="/view/PageName"&gt;PageName&lt;/a&gt;</code>.
    738 	(hint: you could use <code>regexp.ReplaceAllFunc</code> to do this)
    739 	</li>
    740 </ul>
    741