github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/doc/articles/wiki/index.html (about)

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