Lines Matching full:code
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>
32 We will use <code>$</code> to represent the command prompt.
40 Make a new directory for this tutorial inside your <code>GOPATH</code> and cd to it:
49 Create a file named <code>wiki.go</code>, open it in your favorite editor, and
63 We import the <code>fmt</code> and <code>ioutil</code> packages from the Go
65 add more packages to this <code>import</code> declaration.
73 Here, we define <code>Page</code> as a struct with two fields representing
77 {{code "doc/articles/wiki/part1.go" `/^type Page/` `/}/`}}
80 The type <code>[]byte</code> means "a <code>byte</code> slice".
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>
89 The <code>Page</code> struct describes how page data will be stored in memory.
91 <code>save</code> method on <code>Page</code>:
94 {{code "doc/articles/wiki/part1.go" `/^func.*Page.*save/` `/}/`}}
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>."
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.
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
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
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
121 <code>open(2)</code> for details.)
128 {{code "doc/articles/wiki/part1-noerror.go" `/^func loadPage/` `/^}/`}}
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
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
146 But what happens if <code>ReadFile</code> encounters an error? For example,
148 function to return <code>*Page</code> and <code>error</code>.
151 {{code "doc/articles/wiki/part1.go" `/^func loadPage/` `/^}/`}}
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
162 load from a file. Let's write a <code>main</code> function to test what we've
166 {{code "doc/articles/wiki/part1.go" `/^func main/` `/^}/`}}
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
186 (If you're using Windows you must type "<code>wiki</code>" without the
187 "<code>./</code>" to run the program.)
191 <a href="part1.go">Click here to view the code we've written so far.</a>
194 <h2>Introducing the <code>net/http</code> package (an interlude)</h2>
200 {{code "doc/articles/wiki/http-sample.go"}}
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>.
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.)
217 The function <code>handler</code> is of the type <code>http.HandlerFunc</code>.
218 It takes an <code>http.ResponseWriter</code> and an <code>http.Request</code> as
223 An <code>http.ResponseWriter</code> value assembles the HTTP server's response; by writing
228 An <code>http.Request</code> is a data structure that represents the client
229 HTTP request. <code>r.URL.Path</code> is the path component
230 of the request URL. The trailing <code>[1:]</code> means
231 "create a sub-slice of <code>Path</code> from the 1st character to the end."
244 <h2>Using <code>net/http</code> to serve wiki pages</h2>
247 To use the <code>net/http</code> package, it must be imported:
259 Let's create a handler, <code>viewHandler</code> that will allow users to
263 {{code "doc/articles/wiki/part2.go" `/^func viewHandler/` `/^}/`}}
266 First, this function extracts the page title from <code>r.URL.Path</code>,
268 The <code>Path</code> is re-sliced with <code>[len("/view/"):]</code> to drop
269 the leading <code>"/view/"</code> component of the request path.
270 This is because the path will invariably begin with <code>"/view/"</code>,
276 HTML, and writes it to <code>w</code>, the <code>http.ResponseWriter</code>.
280 Again, note the use of <code>_</code> to ignore the <code>error</code>
281 return value from <code>loadPage</code>. This is done here for simplicity
286 To use this handler, we rewrite our <code>main</code> function to
287 initialize <code>http</code> using the <code>viewHandler</code> to handle
288 any requests under the path <code>/view/</code>.
291 {{code "doc/articles/wiki/part2.go" `/^func main/` `/^}/`}}
294 <a href="part2.go">Click here to view the code we've written so far.</a>
298 Let's create some page data (as <code>test.txt</code>), compile our code, and
303 Open <code>test.txt</code> file in your editor, and save the string "Hello world" (without quotes)
313 (If you're using Windows you must type "<code>wiki</code>" without the
314 "<code>./</code>" to run the program.)
318 With this web server running, a visit to <code><a
319 href="http://localhost:8080/view/test">http://localhost:8080/view/test</a></code>
327 handlers: one named <code>editHandler</code> to display an 'edit page' form,
328 and the other named <code>saveHandler</code> to save the data entered via the
333 First, we add them to <code>main()</code>:
336 {{code "doc/articles/wiki/final-noclosure.go" `/^func main/` `/^}/`}}
339 The function <code>editHandler</code> loads the page
340 (or, if it doesn't exist, create an empty <code>Page</code> struct),
344 {{code "doc/articles/wiki/notemplate.go" `/^func editHandler/` `/^}/`}}
351 <h2>The <code>html/template</code> package</h2>
354 The <code>html/template</code> package is part of the Go standard library.
355 We can use <code>html/template</code> to keep the HTML in a separate file,
357 underlying Go code.
361 First, we must add <code>html/template</code> to the list of imports. We
362 also won't be using <code>fmt</code> anymore, so we have to remove that.
375 Open a new file named <code>edit.html</code>, and add the following lines:
378 {{code "doc/articles/wiki/edit.html"}}
381 Modify <code>editHandler</code> to use the template, instead of the hard-coded
385 {{code "doc/articles/wiki/final-noerror.go" `/^func editHandler/` `/^}/`}}
388 The function <code>template.ParseFiles</code> will read the contents of
389 <code>edit.html</code> and return a <code>*template.Template</code>.
393 The method <code>t.Execute</code> executes the template, writing the
394 generated HTML to the <code>http.ResponseWriter</code>.
395 The <code>.Title</code> and <code>.Body</code> dotted identifiers refer to
396 <code>p.Title</code> and <code>p.Body</code>.
401 The <code>printf "%s" .Body</code> instruction is a function call
402 that outputs <code>.Body</code> as a string instead of a stream of bytes,
403 the same as a call to <code>fmt.Printf</code>.
404 The <code>html/template</code> package helps guarantee that only safe and
406 automatically escapes any greater than sign (<code>></code>), replacing it
407 with <code>&gt;</code>, to make sure user data does not corrupt the form
413 <code>viewHandler</code> called <code>view.html</code>:
416 {{code "doc/articles/wiki/view.html"}}
419 Modify <code>viewHandler</code> accordingly:
422 {{code "doc/articles/wiki/final-noerror.go" `/^func viewHandler/` `/^}/`}}
425 Notice that we've used almost exactly the same templating code in both
426 handlers. Let's remove this duplication by moving the templating code
430 {{code "doc/articles/wiki/final-template.go" `/^func renderTemplate/` `/^}/`}}
436 {{code "doc/articles/wiki/final-template.go" `/^func viewHandler/` `/^}/`}}
437 {{code "doc/articles/wiki/final-template.go" `/^func editHandler/` `/^}/`}}
441 <code>main</code>, we can once again build and test our program.
442 <a href="part3.go">Click here to view the code we've written so far.</a>
449 <code>/view/APageThatDoesntExist</code></a>? You'll see a page containing
451 <code>loadPage</code> and continues to try and fill out the template
456 {{code "doc/articles/wiki/part3-errorhandling.go" `/^func viewHandler/` `/^}/`}}
459 The <code>http.Redirect</code> function adds an HTTP status code of
460 <code>http.StatusFound</code> (302) and a <code>Location</code>
467 The function <code>saveHandler</code> will handle the submission of forms
469 <code>main</code>, let's implement the handler:
472 {{code "doc/articles/wiki/final-template.go" `/^func saveHandler/` `/^}/`}}
476 <code>Body</code>, are stored in a new <code>Page</code>.
477 The <code>save()</code> method is then called to write the data to a file,
478 and the client is redirected to the <code>/view/</code> page.
482 The value returned by <code>FormValue</code> is of type <code>string</code>.
483 We must convert that value to <code>[]byte</code> before it will fit into
484 the <code>Page</code> struct. We use <code>[]byte(body)</code> to perform
499 First, let's handle the errors in <code>renderTemplate</code>:
502 {{code "doc/articles/wiki/final-parsetemplate.go" `/^func renderTemplate/` `/^}/`}}
505 The <code>http.Error</code> function sends a specified HTTP response code
511 Now let's fix up <code>saveHandler</code>:
514 {{code "doc/articles/wiki/part3-errorhandling.go" `/^func saveHandler/` `/^}/`}}
517 Any errors that occur during <code>p.save()</code> will be reported
524 There is an inefficiency in this code: <code>renderTemplate</code> calls
525 <code>ParseFiles</code> every time a page is rendered.
526 A better approach would be to call <code>ParseFiles</code> once at program
527 initialization, parsing all templates into a single <code>*Template</code>.
529 <a href="/pkg/html/template/#Template.ExecuteTemplate"><code>ExecuteTemplate</code></a>
534 First we create a global variable named <code>templates</code>, and initialize
535 it with <code>ParseFiles</code>.
538 {{code "doc/articles/wiki/final.go" `/var templates/`}}
541 The function <code>template.Must</code> is a convenience wrapper that panics
542 when passed a non-nil <code>error</code> value, and otherwise returns the
543 <code>*Template</code> unaltered. A panic is appropriate here; if the templates
548 The <code>ParseFiles</code> function takes any number of string arguments that
551 program, we would add their names to the <code>ParseFiles</code> call's
556 We then modify the <code>renderTemplate</code> function to call the
557 <code>templates.ExecuteTemplate</code> method with the name of the appropriate
561 {{code "doc/articles/wiki/final.go" `/func renderTemplate/` `/^}/`}}
565 append <code>".html"</code> to the <code>tmpl</code> argument.
577 First, add <code>"regexp"</code> to the <code>import</code> list.
582 {{code "doc/articles/wiki/final-noclosure.go" `/^var validPath/`}}
585 The function <code>regexp.MustCompile</code> will parse and compile the
586 regular expression, and return a <code>regexp.Regexp</code>.
587 <code>MustCompile</code> is distinct from <code>Compile</code> in that it will
588 panic if the expression compilation fails, while <code>Compile</code> returns
589 an <code>error</code> as a second parameter.
593 Now, let's write a function that uses the <code>validPath</code>
597 {{code "doc/articles/wiki/final-noclosure.go" `/func getTitle/` `/^}/`}}
600 If the title is valid, it will be returned along with a <code>nil</code>
603 handler. To create a new error, we have to import the <code>errors</code>
608 Let's put a call to <code>getTitle</code> in each of the handlers:
611 {{code "doc/articles/wiki/final-noclosure.go" `/^func viewHandler/` `/^}/`}}
612 {{code "doc/articles/wiki/final-noclosure.go" `/^func editHandler/` `/^}/`}}
613 {{code "doc/articles/wiki/final-noclosure.go" `/^func saveHandler/` `/^}/`}}
618 Catching the error condition in each handler introduces a lot of repeated code.
639 type</i>, and returns a function of type <code>http.HandlerFunc</code>
640 (suitable to be passed to the function <code>http.HandleFunc</code>):
654 outside of it. In this case, the variable <code>fn</code> (the single argument
655 to <code>makeHandler</code>) is enclosed by the closure. The variable
656 <code>fn</code> will be one of our save, edit, or view handlers.
660 Now we can take the code from <code>getTitle</code> and use it here
664 {{code "doc/articles/wiki/final.go" `/func makeHandler/` `/^}/`}}
667 The closure returned by <code>makeHandler</code> is a function that takes
668 an <code>http.ResponseWriter</code> and <code>http.Request</code> (in other
669 words, an <code>http.HandlerFunc</code>).
670 The closure extracts the <code>title</code> from the request path, and
671 validates it with the <code>TitleValidator</code> regexp. If the
672 <code>title</code> is invalid, an error will be written to the
673 <code>ResponseWriter</code> using the <code>http.NotFound</code> function.
674 If the <code>title</code> is valid, the enclosed handler function
675 <code>fn</code> will be called with the <code>ResponseWriter</code>,
676 <code>Request</code>, and <code>title</code> as arguments.
680 Now we can wrap the handler functions with <code>makeHandler</code> in
681 <code>main</code>, before they are registered with the <code>http</code>
685 {{code "doc/articles/wiki/final.go" `/func main/` `/^}/`}}
688 Finally we remove the calls to <code>getTitle</code> from the handler functions,
692 {{code "doc/articles/wiki/final.go" `/^func viewHandler/` `/^}/`}}
693 {{code "doc/articles/wiki/final.go" `/^func editHandler/` `/^}/`}}
694 {{code "doc/articles/wiki/final.go" `/^func saveHandler/` `/^}/`}}
699 <a href="final.go">Click here to view the final code listing.</a>
703 Recompile the code, and run the app:
724 <li>Store templates in <code>tmpl/</code> and page data in <code>data/</code>.
726 <code>/view/FrontPage</code>.</li>
730 <code>[PageName]</code> to <br>
731 <code><a href="/view/PageName">PageName</a></code>.
732 (hint: you could use <code>regexp.ReplaceAllFunc</code> to do this)