]> Cypherpunks repositories - gostls13.git/commitdiff
doc/codelab/wiki: update to work with template changes, add to run.bash
authorAndrew Gerrand <adg@golang.org>
Wed, 26 Jan 2011 04:56:52 +0000 (14:56 +1000)
committerAndrew Gerrand <adg@golang.org>
Wed, 26 Jan 2011 04:56:52 +0000 (14:56 +1000)
Fixes #1444.

R=rsc, r
CC=golang-dev
https://golang.org/cl/3979045

17 files changed:
doc/codelab/wiki/edit.html
doc/codelab/wiki/final-noclosure.go
doc/codelab/wiki/final-noerror.go
doc/codelab/wiki/final-parsetemplate.go
doc/codelab/wiki/final-template.go
doc/codelab/wiki/final.go
doc/codelab/wiki/htmlify.go
doc/codelab/wiki/index.html
doc/codelab/wiki/notemplate.go
doc/codelab/wiki/part1-noerror.go
doc/codelab/wiki/part1.go
doc/codelab/wiki/part2.go
doc/codelab/wiki/srcextract.go
doc/codelab/wiki/test_edit.good
doc/codelab/wiki/view.html
doc/codelab/wiki/wiki.html
src/run.bash

index 71a919496f7f4b84da1d4b2bc9fe18b2f5a3154b..66dfeb511eb62c34ed0cf6c4b25e0d3377550905 100644 (file)
@@ -1,6 +1,6 @@
-<h1>Editing {title}</h1>
+<h1>Editing {Title}</h1>
 
-<form action="/save/{title}" method="POST">
-<div><textarea name="body" rows="20" cols="80">{body|html}</textarea></div>
+<form action="/save/{Title}" method="POST">
+<div><textarea name="Body" rows="20" cols="80">{Body|html}</textarea></div>
 <div><input type="submit" value="Save"></div>
 </form>
index 2f48565ca2b9e46796d7c51b7c1029a06a3b139b..99121f298b8bd2b2c366f36dc037989a4bdc90e0 100644 (file)
@@ -8,23 +8,23 @@ import (
        "template"
 )
 
-type page struct {
-       title string
-       body  []byte
+type Page struct {
+       Title string
+       Body  []byte
 }
 
-func (p *page) save() os.Error {
-       filename := p.title + ".txt"
-       return ioutil.WriteFile(filename, p.body, 0600)
+func (p *Page) save() os.Error {
+       filename := p.Title + ".txt"
+       return ioutil.WriteFile(filename, p.Body, 0600)
 }
 
-func loadPage(title string) (*page, os.Error) {
+func loadPage(title string) (*Page, os.Error) {
        filename := title + ".txt"
        body, err := ioutil.ReadFile(filename)
        if err != nil {
                return nil, err
        }
-       return &page{title: title, body: body}, nil
+       return &Page{Title: title, Body: body}, nil
 }
 
 func viewHandler(w http.ResponseWriter, r *http.Request) {
@@ -47,7 +47,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) {
        }
        p, err := loadPage(title)
        if err != nil {
-               p = &page{title: title}
+               p = &Page{Title: title}
        }
        renderTemplate(w, "edit", p)
 }
@@ -58,7 +58,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) {
                return
        }
        body := r.FormValue("body")
-       p := &page{title: title, body: []byte(body)}
+       p := &Page{Title: title, Body: []byte(body)}
        err = p.save()
        if err != nil {
                http.Error(w, err.String(), http.StatusInternalServerError)
@@ -67,7 +67,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) {
        http.Redirect(w, r, "/view/"+title, http.StatusFound)
 }
 
-func renderTemplate(w http.ResponseWriter, tmpl string, p *page) {
+func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
        t, err := template.ParseFile(tmpl+".html", nil)
        if err != nil {
                http.Error(w, err.String(), http.StatusInternalServerError)
index cf4852265415cad902b8e61b3306a878637b83cc..0f18912d2e6cac00634ca3146500d7f23533cf45 100644 (file)
@@ -7,23 +7,23 @@ import (
        "template"
 )
 
-type page struct {
-       title string
-       body  []byte
+type Page struct {
+       Title string
+       Body  []byte
 }
 
-func (p *page) save() os.Error {
-       filename := p.title + ".txt"
-       return ioutil.WriteFile(filename, p.body, 0600)
+func (p *Page) save() os.Error {
+       filename := p.Title + ".txt"
+       return ioutil.WriteFile(filename, p.Body, 0600)
 }
 
-func loadPage(title string) (*page, os.Error) {
+func loadPage(title string) (*Page, os.Error) {
        filename := title + ".txt"
        body, err := ioutil.ReadFile(filename)
        if err != nil {
                return nil, err
        }
-       return &page{title: title, body: body}, nil
+       return &Page{Title: title, Body: body}, nil
 }
 
 const lenPath = len("/view/")
@@ -32,7 +32,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) {
        title := r.URL.Path[lenPath:]
        p, err := loadPage(title)
        if err != nil {
-               p = &page{title: title}
+               p = &Page{Title: title}
        }
        t, _ := template.ParseFile("edit.html", nil)
        t.Execute(p, w)
index f02d116b2af612bcb11ba194fd79b1f275e951ce..ea897760159a56f1f753dc72bb127ae8982c6095 100644 (file)
@@ -8,23 +8,23 @@ import (
        "template"
 )
 
-type page struct {
-       title string
-       body  []byte
+type Page struct {
+       Title string
+       Body  []byte
 }
 
-func (p *page) save() os.Error {
-       filename := p.title + ".txt"
-       return ioutil.WriteFile(filename, p.body, 0600)
+func (p *Page) save() os.Error {
+       filename := p.Title + ".txt"
+       return ioutil.WriteFile(filename, p.Body, 0600)
 }
 
-func loadPage(title string) (*page, os.Error) {
+func loadPage(title string) (*Page, os.Error) {
        filename := title + ".txt"
        body, err := ioutil.ReadFile(filename)
        if err != nil {
                return nil, err
        }
-       return &page{title: title, body: body}, nil
+       return &Page{Title: title, Body: body}, nil
 }
 
 func viewHandler(w http.ResponseWriter, r *http.Request, title string) {
@@ -39,14 +39,14 @@ func viewHandler(w http.ResponseWriter, r *http.Request, title string) {
 func editHandler(w http.ResponseWriter, r *http.Request, title string) {
        p, err := loadPage(title)
        if err != nil {
-               p = &page{title: title}
+               p = &Page{Title: title}
        }
        renderTemplate(w, "edit", p)
 }
 
 func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
        body := r.FormValue("body")
-       p := &page{title: title, body: []byte(body)}
+       p := &Page{Title: title, Body: []byte(body)}
        err := p.save()
        if err != nil {
                http.Error(w, err.String(), http.StatusInternalServerError)
@@ -55,7 +55,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
        http.Redirect(w, r, "/view/"+title, http.StatusFound)
 }
 
-func renderTemplate(w http.ResponseWriter, tmpl string, p *page) {
+func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
        t, err := template.ParseFile(tmpl+".html", nil)
        if err != nil {
                http.Error(w, err.String(), http.StatusInternalServerError)
index 0bb133d3a1570c4f594b865a5a8312671f9254d4..4d6a2cfaba3e7f130db03b183d6de8d9d71cd8c2 100644 (file)
@@ -7,23 +7,23 @@ import (
        "template"
 )
 
-type page struct {
-       title string
-       body  []byte
+type Page struct {
+       Title string
+       Body  []byte
 }
 
-func (p *page) save() os.Error {
-       filename := p.title + ".txt"
-       return ioutil.WriteFile(filename, p.body, 0600)
+func (p *Page) save() os.Error {
+       filename := p.Title + ".txt"
+       return ioutil.WriteFile(filename, p.Body, 0600)
 }
 
-func loadPage(title string) (*page, os.Error) {
+func loadPage(title string) (*Page, os.Error) {
        filename := title + ".txt"
        body, err := ioutil.ReadFile(filename)
        if err != nil {
                return nil, err
        }
-       return &page{title: title, body: body}, nil
+       return &Page{Title: title, Body: body}, nil
 }
 
 const lenPath = len("/view/")
@@ -32,7 +32,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) {
        title := r.URL.Path[lenPath:]
        p, err := loadPage(title)
        if err != nil {
-               p = &page{title: title}
+               p = &Page{Title: title}
        }
        renderTemplate(w, "edit", p)
 }
@@ -46,12 +46,12 @@ func viewHandler(w http.ResponseWriter, r *http.Request) {
 func saveHandler(w http.ResponseWriter, r *http.Request) {
        title := r.URL.Path[lenPath:]
        body := r.FormValue("body")
-       p := &page{title: title, body: []byte(body)}
+       p := &Page{Title: title, Body: []byte(body)}
        p.save()
        http.Redirect(w, r, "/view/"+title, http.StatusFound)
 }
 
-func renderTemplate(w http.ResponseWriter, tmpl string, p *page) {
+func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
        t, _ := template.ParseFile(tmpl+".html", nil)
        t.Execute(p, w)
 }
index 0c0206bc0c2121accebb8dd8fdb69c833ad51f9f..8ecd97d7484432107495ba05b938bab8df0c0225 100644 (file)
@@ -8,23 +8,23 @@ import (
        "template"
 )
 
-type page struct {
-       title string
-       body  []byte
+type Page struct {
+       Title string
+       Body  []byte
 }
 
-func (p *page) save() os.Error {
-       filename := p.title + ".txt"
-       return ioutil.WriteFile(filename, p.body, 0600)
+func (p *Page) save() os.Error {
+       filename := p.Title + ".txt"
+       return ioutil.WriteFile(filename, p.Body, 0600)
 }
 
-func loadPage(title string) (*page, os.Error) {
+func loadPage(title string) (*Page, os.Error) {
        filename := title + ".txt"
        body, err := ioutil.ReadFile(filename)
        if err != nil {
                return nil, err
        }
-       return &page{title: title, body: body}, nil
+       return &Page{Title: title, Body: body}, nil
 }
 
 func viewHandler(w http.ResponseWriter, r *http.Request, title string) {
@@ -39,14 +39,14 @@ func viewHandler(w http.ResponseWriter, r *http.Request, title string) {
 func editHandler(w http.ResponseWriter, r *http.Request, title string) {
        p, err := loadPage(title)
        if err != nil {
-               p = &page{title: title}
+               p = &Page{Title: title}
        }
        renderTemplate(w, "edit", p)
 }
 
 func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
        body := r.FormValue("body")
-       p := &page{title: title, body: []byte(body)}
+       p := &Page{Title: title, Body: []byte(body)}
        err := p.save()
        if err != nil {
                http.Error(w, err.String(), http.StatusInternalServerError)
@@ -63,7 +63,7 @@ func init() {
        }
 }
 
-func renderTemplate(w http.ResponseWriter, tmpl string, p *page) {
+func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
        err := templates[tmpl].Execute(p, w)
        if err != nil {
                http.Error(w, err.String(), http.StatusInternalServerError)
index 4a52e077f2848c673ef4e2c88c8bfaf97437ceb0..456d06fd525d2d58d947f7053d11668245b8149b 100644 (file)
@@ -8,5 +8,5 @@ import (
 
 func main() {
        b, _ := ioutil.ReadAll(os.Stdin)
-       template.HTMLFormatter(os.Stdout, b, "")
+       template.HTMLFormatter(os.Stdout, "", b)
 }
index c494a3cedcd30d87abd4c91ba5080684fe0e957e..e4273de7a65148acff2acbf211df74d2dfc9eefe 100644 (file)
@@ -71,14 +71,14 @@ declaration.
 <p>
 Let's start by defining the data structures. A wiki consists of a series of
 interconnected pages, each of which has a title and a body (the page content).
-Here, we define <code>page</code> as a struct with two fields representing
+Here, we define <code>Page</code> as a struct with two fields representing
 the title and body.
 </p>
 
 <pre>
-type page struct {
-       title   string
-       body    []byte
+type Page struct {
+       Title   string
+       Body    []byte
 }
 </pre>
 
@@ -86,33 +86,33 @@ type page struct {
 The type <code>[]byte</code> means "a <code>byte</code> slice". 
 (See <a href="http://golang.org/doc/effective_go.html#slices">Effective Go</a> 
 for more on slices.)  
-The <code>body</code> element is a <code>[]byte</code> rather than
+The <code>Body</code> element is a <code>[]byte</code> rather than
 <code>string</code> because that is the type expected by the <code>io</code>
 libraries we will use, as you'll see below.
 </p>
 
 <p>
-The <code>page</code> struct describes how page data will be stored in memory. 
+The <code>Page</code> struct describes how page data will be stored in memory. 
 But what about persistent storage? We can address that by creating a 
-<code>save</code> method on <code>page</code>:
+<code>save</code> method on <code>Page</code>:
 </p>
 
 <pre>
-func (p *page) save() os.Error {
-       filename := p.title + &#34;.txt&#34;
-       return ioutil.WriteFile(filename, p.body, 0600)
+func (p *Page) save() os.Error {
+       filename := p.Title + &#34;.txt&#34;
+       return ioutil.WriteFile(filename, p.Body, 0600)
 }
 </pre>
 
 <p>
 This method's signature reads: "This is a method named <code>save</code> that
-takes as its receiver <code>p</code>, a pointer to <code>page</code> . It takes
+takes as its receiver <code>p</code>, a pointer to <code>Page</code> . It takes
 no parameters, and returns a value of type <code>os.Error</code>." 
 </p>
 
 <p>
-This method will save the <code>page</code>'s <code>body</code> to a text 
-file. For simplicity, we will use the <code>title</code> as the file name.
+This method will save the <code>Page</code>'s <code>Body</code> to a text 
+file. For simplicity, we will use the <code>Title</code> as the file name.
 </p>
 
 <p>
@@ -120,7 +120,7 @@ The <code>save</code> method returns an <code>os.Error</code> value because
 that is the return type of <code>WriteFile</code> (a standard library function
 that writes a byte slice to a file).  The <code>save</code> method returns the
 error value, to let the application handle it should anything go wrong while
-writing the file.  If all goes well, <code>page.save()</code> will return
+writing the file.  If all goes well, <code>Page.save()</code> will return
 <code>nil</code> (the zero-value for pointers, interfaces, and some other 
 types).
 </p>
@@ -137,17 +137,17 @@ We will want to load pages, too:
 </p>
 
 <pre>
-func loadPage(title string) *page {
+func loadPage(title string) *Page {
        filename := title + &#34;.txt&#34;
        body, _ := ioutil.ReadFile(filename)
-       return &amp;page{title: title, body: body}
+       return &amp;Page{Title: title, Body: body}
 }
 </pre>
 
 <p>
 The function <code>loadPage</code> constructs the file name from
-<code>title</code>, reads the file's contents into a new
-<code>page</code>, and returns a pointer to that new <code>page</code>.
+<code>Title</code>, reads the file's contents into a new
+<code>Page</code>, and returns a pointer to that new <code>page</code>.
 </p>
 
 <p>
@@ -161,23 +161,23 @@ error return value (in essence, assigning the value to nothing).
 <p>
 But what happens if <code>ReadFile</code> encounters an error?  For example,
 the file might not exist. We should not ignore such errors.  Let's modify the
-function to return <code>*page</code> and <code>os.Error</code>.
+function to return <code>*Page</code> and <code>os.Error</code>.
 </p>
 
 <pre>
-func loadPage(title string) (*page, os.Error) {
+func loadPage(title string) (*Page, os.Error) {
        filename := title + &#34;.txt&#34;
        body, err := ioutil.ReadFile(filename)
        if err != nil {
                return nil, err
        }
-       return &amp;page{title: title, body: body}, nil
+       return &amp;Page{Title: title, Body: body}, nil
 }
 </pre>
 
 <p>
 Callers of this function can now check the second parameter; if it is
-<code>nil</code> then it has successfully loaded a page. If not, it will be an
+<code>nil</code> then it has successfully loaded a Page. If not, it will be an
 <code>os.Error</code> that can be handled by the caller (see the <a
 href="http://golang.org/pkg/os/#Error">os package documentation</a> for 
 details).
@@ -191,17 +191,17 @@ written:
 
 <pre>
 func main() {
-       p1 := &amp;page{title: &#34;TestPage&#34;, body: []byte(&#34;This is a sample page.&#34;)}
+       p1 := &amp;Page{Title: &#34;TestPage&#34;, Body: []byte(&#34;This is a sample Page.&#34;)}
        p1.save()
        p2, _ := loadPage(&#34;TestPage&#34;)
-       fmt.Println(string(p2.body))
+       fmt.Println(string(p2.Body))
 }
 </pre>
 
 <p>
 After compiling and executing this code, a file named <code>TestPage.txt</code>
 would be created, containing the contents of <code>p1</code>. The file would
-then be read into the struct <code>p2</code>, and its <code>body</code> element
+then be read into the struct <code>p2</code>, and its <code>Body</code> element
 printed to the screen.
 </p>
 
@@ -317,7 +317,7 @@ const lenPath = len(&#34;/view/&#34;)
 func viewHandler(w http.ResponseWriter, r *http.Request) {
        title := r.URL.Path[lenPath:]
        p, _ := loadPage(title)
-       fmt.Fprintf(w, &#34;&lt;h1&gt;%s&lt;/h1&gt;&lt;div&gt;%s&lt;/div&gt;&#34;, p.title, p.body)
+       fmt.Fprintf(w, &#34;&lt;h1&gt;%s&lt;/h1&gt;&lt;div&gt;%s&lt;/div&gt;&#34;, p.Title, p.Body)
 }
 </pre>
 
@@ -377,7 +377,7 @@ href="http://localhost:8080/view/test">http://localhost:8080/view/test</a></code
 should show a page titled "test" containing the words "Hello world".
 </p>
 
-<h2>Editing pages</h2>
+<h2>Editing Pages</h2>
 
 <p>
 A wiki is not a wiki without the ability to edit pages. Let's create two new
@@ -401,7 +401,7 @@ func main() {
 
 <p>
 The function <code>editHandler</code> loads the page 
-(or, if it doesn't exist, create an empty <code>page</code> struct), 
+(or, if it doesn't exist, create an empty <code>Page</code> struct), 
 and displays an HTML form.
 </p>
 
@@ -410,14 +410,14 @@ func editHandler(w http.ResponseWriter, r *http.Request) {
        title := r.URL.Path[lenPath:]
        p, err := loadPage(title)
        if err != nil {
-               p = &amp;page{title: title}
+               p = &amp;Page{Title: title}
        }
        fmt.Fprintf(w, &#34;&lt;h1&gt;Editing %s&lt;/h1&gt;&#34;+
                &#34;&lt;form action=\&#34;/save/%s\&#34; method=\&#34;POST\&#34;&gt;&#34;+
                &#34;&lt;textarea name=\&#34;body\&#34;&gt;%s&lt;/textarea&gt;&lt;br&gt;&#34;+
                &#34;&lt;input type=\&#34;submit\&#34; value=\&#34;Save\&#34;&gt;&#34;+
                &#34;&lt;/form&gt;&#34;,
-               p.title, p.title, p.body)
+               p.Title, p.Title, p.Body)
 }
 </pre>
 
@@ -454,10 +454,10 @@ Open a new file named <code>edit.html</code>, and add the following lines:
 </p>
 
 <pre>
-&lt;h1&gt;Editing {title}&lt;/h1&gt;
+&lt;h1&gt;Editing {Title}&lt;/h1&gt;
 
-&lt;form action=&#34;/save/{title}&#34; method=&#34;POST&#34;&gt;
-&lt;div&gt;&lt;textarea name=&#34;body&#34; rows=&#34;20&#34; cols=&#34;80&#34;&gt;{body|html}&lt;/textarea&gt;&lt;/div&gt;
+&lt;form action=&#34;/save/{Title}&#34; method=&#34;POST&#34;&gt;
+&lt;div&gt;&lt;textarea name=&#34;Body&#34; rows=&#34;20&#34; cols=&#34;80&#34;&gt;{Body|html}&lt;/textarea&gt;&lt;/div&gt;
 &lt;div&gt;&lt;input type=&#34;submit&#34; value=&#34;Save&#34;&gt;&lt;/div&gt;
 &lt;/form&gt;
 </pre>
@@ -472,7 +472,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) {
        title := r.URL.Path[lenPath:]
        p, err := loadPage(title)
        if err != nil {
-               p = &amp;page{title: title}
+               p = &amp;Page{Title: title}
        }
        t, _ := template.ParseFile(&#34;edit.html&#34;, nil)
        t.Execute(p, w)
@@ -486,15 +486,15 @@ The function <code>template.ParseFile</code> will read the contents of
 
 <p>
 The method <code>t.Execute</code> replaces all occurrences of 
-<code>{title}</code> and <code>{body}</code> with the values of 
-<code>p.title</code> and <code>p.body</code>, and writes the resultant
+<code>{Title}</code> and <code>{Body}</code> with the values of 
+<code>p.Title</code> and <code>p.Body</code>, and writes the resultant
 HTML to the <code>http.ResponseWriter</code>.
 </p>
 
 <p>
-Note that we've used <code>{body|html}</code> in the above template.  
+Note that we've used <code>{Body|html}</code> in the above template.  
 The <code>|html</code> part asks the template engine to pass the value
-<code>body</code> through the <code>html</code> formatter before outputting it,
+<code>Body</code> through the <code>html</code> formatter before outputting it,
 which escapes HTML characters (such as replacing <code>&gt;</code> with 
 <code>&amp;gt;</code>). 
 This will prevent user data from corrupting the form HTML. 
@@ -511,11 +511,11 @@ While we're working with templates, let's create a template for our
 </p>
 
 <pre>
-&lt;h1&gt;{title}&lt;/h1&gt;
+&lt;h1&gt;{Title}&lt;/h1&gt;
 
-&lt;p&gt;[&lt;a href=&#34;/edit/{title}&#34;&gt;edit&lt;/a&gt;]&lt;/p&gt;
+&lt;p&gt;[&lt;a href=&#34;/edit/{Title}&#34;&gt;edit&lt;/a&gt;]&lt;/p&gt;
 
-&lt;div&gt;{body}&lt;/div&gt;
+&lt;div&gt;{Body}&lt;/div&gt;
 </pre>
 
 <p>
@@ -548,12 +548,12 @@ func editHandler(w http.ResponseWriter, r *http.Request) {
        title := r.URL.Path[lenPath:]
        p, err := loadPage(title)
        if err != nil {
-               p = &amp;page{title: title}
+               p = &amp;Page{Title: title}
        }
        renderTemplate(w, &#34;edit&#34;, p)
 }
 
-func renderTemplate(w http.ResponseWriter, tmpl string, p *page) {
+func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
        t, _ := template.ParseFile(tmpl+&#34;.html&#34;, nil)
        t.Execute(p, w)
 }
@@ -568,8 +568,8 @@ The handlers are now shorter and simpler.
 <p>
 What if you visit <code>/view/APageThatDoesntExist</code>? The program will 
 crash. This is because it ignores the error return value from
-<code>loadPage</code>. Instead, if the requested page doesn't exist, it should 
-redirect the client to the edit page so the content may be created:
+<code>loadPage</code>. Instead, if the requested Page doesn't exist, it should 
+redirect the client to the edit Page so the content may be created:
 </p>
 
 <pre>
@@ -589,7 +589,7 @@ The <code>http.Redirect</code> function adds an HTTP status code of
 header to the HTTP response.
 </p>
 
-<h2>Saving pages</h2>
+<h2>Saving Pages</h2>
 
 <p>
 The function <code>saveHandler</code> will handle the form submission. 
@@ -599,7 +599,7 @@ The function <code>saveHandler</code> will handle the form submission.
 func saveHandler(w http.ResponseWriter, r *http.Request) {
        title := r.URL.Path[lenPath:]
        body := r.FormValue(&#34;body&#34;)
-       p := &amp;page{title: title, body: []byte(body)}
+       p := &amp;Page{Title: title, Body: []byte(body)}
        p.save()
        http.Redirect(w, r, &#34;/view/&#34;+title, http.StatusFound)
 }
@@ -607,7 +607,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) {
 
 <p>
 The page title (provided in the URL) and the form's only field, 
-<code>body</code>, are stored in a new <code>page</code>. 
+<code>Body</code>, are stored in a new <code>Page</code>. 
 The <code>save()</code> method is then called to write the data to a file,
 and the client is redirected to the <code>/view/</code> page.
 </p>
@@ -615,7 +615,7 @@ and the client is redirected to the <code>/view/</code> page.
 <p>
 The value returned by <code>FormValue</code> is of type <code>string</code>.
 We must convert that value to <code>[]byte</code> before it will fit into 
-the <code>page</code> struct.  We use <code>[]byte(body)</code> to perform
+the <code>Page</code> struct.  We use <code>[]byte(body)</code> to perform
 the conversion.
 </p>
 
@@ -634,7 +634,7 @@ First, let's handle the errors in <code>renderTemplate</code>:
 </p>
 
 <pre>
-func renderTemplate(w http.ResponseWriter, tmpl string, p *page) {
+func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
        t, err := template.ParseFile(tmpl+&#34;.html&#34;, nil)
        if err != nil {
                http.Error(w, err.String(), http.StatusInternalServerError)
@@ -660,7 +660,7 @@ Now let's fix up <code>saveHandler</code>:
 <pre>
 func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
        body := r.FormValue(&#34;body&#34;)
-       p := &amp;page{title: title, body: []byte(body)}
+       p := &amp;Page{Title: title, Body: []byte(body)}
        err := p.save()
        if err != nil {
                http.Error(w, err.String(), http.StatusInternalServerError)
@@ -725,7 +725,7 @@ the <code>Execute</code> method on the appropriate <code>Template</code> from
 <code>templates</code>:
 
 <pre>
-func renderTemplate(w http.ResponseWriter, tmpl string, p *page) {
+func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
        err := templates[tmpl].Execute(p, w)
        if err != nil {
                http.Error(w, err.String(), http.StatusInternalServerError)
@@ -747,7 +747,6 @@ Then we can create a global variable to store our validation regexp:
 </p>
 
 <pre>
-var titleValidator = regexp.MustCompile(&#34;^[a-zA-Z0-9]+$&#34;)
 </pre>
 
 <p>
@@ -761,7 +760,7 @@ the expression compilation fails, while <code>Compile</code> returns an
 
 <p>
 Now, let's write a function that extracts the title string from the request 
-URL, and tests it against our <code>titleValidator</code> expression:
+URL, and tests it against our <code>TitleValidator</code> expression:
 </p>
 
 <pre>
@@ -807,7 +806,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) {
        }
        p, err := loadPage(title)
        if err != nil {
-               p = &amp;page{title: title}
+               p = &amp;Page{Title: title}
        }
        renderTemplate(w, &#34;edit&#34;, p)
 }
@@ -818,7 +817,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) {
                return
        }
        body := r.FormValue(&#34;body&#34;)
-       p := &amp;page{title: title, body: []byte(body)}
+       p := &amp;Page{Title: title, Body: []byte(body)}
        err = p.save()
        if err != nil {
                http.Error(w, err.String(), http.StatusInternalServerError)
@@ -895,7 +894,7 @@ The closure returned by <code>makeHandler</code> is a function that takes
 an <code>http.ResponseWriter</code> and <code>http.Request</code> (in other
 words, an <code>http.HandlerFunc</code>). 
 The closure extracts the <code>title</code> from the request path, and
-validates it with the <code>titleValidator</code> regexp. If the
+validates it with the <code>TitleValidator</code> regexp. If the
 <code>title</code> is invalid, an error will be written to the
 <code>ResponseWriter</code> using the <code>http.NotFound</code> function. 
 If the <code>title</code> is valid, the enclosed handler function
@@ -936,14 +935,14 @@ func viewHandler(w http.ResponseWriter, r *http.Request, title string) {
 func editHandler(w http.ResponseWriter, r *http.Request, title string) {
        p, err := loadPage(title)
        if err != nil {
-               p = &amp;page{title: title}
+               p = &amp;Page{Title: title}
        }
        renderTemplate(w, &#34;edit&#34;, p)
 }
 
 func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
        body := r.FormValue(&#34;body&#34;)
-       p := &amp;page{title: title, body: []byte(body)}
+       p := &amp;Page{Title: title, Body: []byte(body)}
        err := p.save()
        if err != nil {
                http.Error(w, err.String(), http.StatusInternalServerError)
index c1f952c83820f23075e70a8f4079bfb87aada379..9cbe9ad768ec833c7da23098d083c9859f8d2353 100644 (file)
@@ -7,23 +7,23 @@ import (
        "os"
 )
 
-type page struct {
-       title string
-       body  []byte
+type Page struct {
+       Title string
+       Body  []byte
 }
 
-func (p *page) save() os.Error {
-       filename := p.title + ".txt"
-       return ioutil.WriteFile(filename, p.body, 0600)
+func (p *Page) save() os.Error {
+       filename := p.Title + ".txt"
+       return ioutil.WriteFile(filename, p.Body, 0600)
 }
 
-func loadPage(title string) (*page, os.Error) {
+func loadPage(title string) (*Page, os.Error) {
        filename := title + ".txt"
        body, err := ioutil.ReadFile(filename)
        if err != nil {
                return nil, err
        }
-       return &page{title: title, body: body}, nil
+       return &Page{Title: title, Body: body}, nil
 }
 
 const lenPath = len("/view/")
@@ -31,21 +31,21 @@ const lenPath = len("/view/")
 func viewHandler(w http.ResponseWriter, r *http.Request) {
        title := r.URL.Path[lenPath:]
        p, _ := loadPage(title)
-       fmt.Fprintf(w, "<h1>%s</h1><div>%s</div>", p.title, p.body)
+       fmt.Fprintf(w, "<h1>%s</h1><div>%s</div>", p.Title, p.Body)
 }
 
 func editHandler(w http.ResponseWriter, r *http.Request) {
        title := r.URL.Path[lenPath:]
        p, err := loadPage(title)
        if err != nil {
-               p = &page{title: title}
+               p = &Page{Title: title}
        }
        fmt.Fprintf(w, "<h1>Editing %s</h1>"+
                "<form action=\"/save/%s\" method=\"POST\">"+
                "<textarea name=\"body\">%s</textarea><br>"+
                "<input type=\"submit\" value=\"Save\">"+
                "</form>",
-               p.title, p.title, p.body)
+               p.Title, p.Title, p.Body)
 }
 
 func main() {
index 39e8331e393e1593c138f7e37071d4b3bae600bc..14cfc321a7846226b12a7805512acf0bac71a68f 100644 (file)
@@ -6,25 +6,25 @@ import (
        "os"
 )
 
-type page struct {
-       title string
-       body  []byte
+type Page struct {
+       Title string
+       Body  []byte
 }
 
-func (p *page) save() os.Error {
-       filename := p.title + ".txt"
-       return ioutil.WriteFile(filename, p.body, 0600)
+func (p *Page) save() os.Error {
+       filename := p.Title + ".txt"
+       return ioutil.WriteFile(filename, p.Body, 0600)
 }
 
-func loadPage(title string) *page {
+func loadPage(title string) *Page {
        filename := title + ".txt"
        body, _ := ioutil.ReadFile(filename)
-       return &page{title: title, body: body}
+       return &Page{Title: title, Body: body}
 }
 
 func main() {
-       p1 := &page{title: "TestPage", body: []byte("This is a sample page.")}
+       p1 := &Page{Title: "TestPage", Body: []byte("This is a sample page.")}
        p1.save()
        p2 := loadPage("TestPage")
-       fmt.Println(string(p2.body))
+       fmt.Println(string(p2.Body))
 }
index f3678baa51f833d8ada0a3e54b9d1d869213e85f..4b0654f8b12c4e0f7157d04a8d217985310b31c9 100644 (file)
@@ -6,28 +6,28 @@ import (
        "os"
 )
 
-type page struct {
-       title string
-       body  []byte
+type Page struct {
+       Title string
+       Body  []byte
 }
 
-func (p *page) save() os.Error {
-       filename := p.title + ".txt"
-       return ioutil.WriteFile(filename, p.body, 0600)
+func (p *Page) save() os.Error {
+       filename := p.Title + ".txt"
+       return ioutil.WriteFile(filename, p.Body, 0600)
 }
 
-func loadPage(title string) (*page, os.Error) {
+func loadPage(title string) (*Page, os.Error) {
        filename := title + ".txt"
        body, err := ioutil.ReadFile(filename)
        if err != nil {
                return nil, err
        }
-       return &page{title: title, body: body}, nil
+       return &Page{Title: title, Body: body}, nil
 }
 
 func main() {
-       p1 := &page{title: "TestPage", body: []byte("This is a sample page.")}
+       p1 := &Page{Title: "TestPage", Body: []byte("This is a sample Page.")}
        p1.save()
        p2, _ := loadPage("TestPage")
-       fmt.Println(string(p2.body))
+       fmt.Println(string(p2.Body))
 }
index 8d4454a74abc3ccbfdcc73f74bef2370b5a8d4b8..d57c3a01f1b641d2b7cdc5360d6bda872d1413b4 100644 (file)
@@ -7,23 +7,23 @@ import (
        "os"
 )
 
-type page struct {
-       title string
-       body  []byte
+type Page struct {
+       Title string
+       Body  []byte
 }
 
-func (p *page) save() os.Error {
-       filename := p.title + ".txt"
-       return ioutil.WriteFile(filename, p.body, 0600)
+func (p *Page) save() os.Error {
+       filename := p.Title + ".txt"
+       return ioutil.WriteFile(filename, p.Body, 0600)
 }
 
-func loadPage(title string) (*page, os.Error) {
+func loadPage(title string) (*Page, os.Error) {
        filename := title + ".txt"
        body, err := ioutil.ReadFile(filename)
        if err != nil {
                return nil, err
        }
-       return &page{title: title, body: body}, nil
+       return &Page{Title: title, Body: body}, nil
 }
 
 const lenPath = len("/view/")
@@ -31,7 +31,7 @@ const lenPath = len("/view/")
 func viewHandler(w http.ResponseWriter, r *http.Request) {
        title := r.URL.Path[lenPath:]
        p, _ := loadPage(title)
-       fmt.Fprintf(w, "<h1>%s</h1><div>%s</div>", p.title, p.body)
+       fmt.Fprintf(w, "<h1>%s</h1><div>%s</div>", p.Title, p.Body)
 }
 
 func main() {
index 0addc61c4e71c239c32fe4d0398f05ac19b9be87..fdb7a5e1fcd575d3cd26a38d0ecbecca028518c7 100644 (file)
@@ -6,6 +6,7 @@ import (
        "go/parser"
        "go/printer"
        "go/ast"
+       "go/token"
        "log"
        "os"
 )
@@ -25,7 +26,8 @@ func main() {
                os.Exit(2)
        }
        // load file
-       file, err := parser.ParseFile(*srcFn, nil, 0)
+       fs := token.NewFileSet()
+       file, err := parser.ParseFile(fs, *srcFn, nil, 0)
        if err != nil {
                log.Exit(err)
        }
@@ -47,7 +49,7 @@ func main() {
                os.Exit(1)
        }
        b := new(bytes.Buffer)
-       p.Fprint(b, file)
+       p.Fprint(b, fs, file)
        // drop package declaration
        if !*showPkg {
                for {
index 36c6dbb7322509dc35995a17b139ba884a3567fd..e4edf8cb237b1c6c51b5dca316302ee3caf4ea49 100644 (file)
@@ -1,6 +1,6 @@
 <h1>Editing Test</h1>
 
 <form action="/save/Test" method="POST">
-<div><textarea name="body" rows="20" cols="80"></textarea></div>
+<div><textarea name="Body" rows="20" cols="80"></textarea></div>
 <div><input type="submit" value="Save"></div>
 </form>
index a46622d01f4d91f6fa26dca7180636aada84cccc..ca2ffc20b6401dd74e705f409a5180cc51d361bd 100644 (file)
@@ -1,5 +1,5 @@
-<h1>{title}</h1>
+<h1>{Title}</h1>
 
-<p>[<a href="/edit/{title}">edit</a>]</p>
+<p>[<a href="/edit/{Title}">edit</a>]</p>
 
-<div>{body}</div>
+<div>{Body}</div>
index 919385edf35c010a073ed53e348768dcc5f42d98..ff2c3088b0169a8945cdf1a170d8cdd4aba70c9c 100644 (file)
@@ -71,27 +71,27 @@ declaration.
 <p>
 Let's start by defining the data structures. A wiki consists of a series of
 interconnected pages, each of which has a title and a body (the page content).
-Here, we define <code>page</code> as a struct with two fields representing
+Here, we define <code>Page</code> as a struct with two fields representing
 the title and body.
 </p>
 
 <pre>
-!./srcextract.bin -src=part1.go -name=page
+!./srcextract.bin -src=part1.go -name=Page
 </pre>
 
 <p>
 The type <code>[]byte</code> means "a <code>byte</code> slice". 
 (See <a href="http://golang.org/doc/effective_go.html#slices">Effective Go</a> 
 for more on slices.)  
-The <code>body</code> element is a <code>[]byte</code> rather than
+The <code>Body</code> element is a <code>[]byte</code> rather than
 <code>string</code> because that is the type expected by the <code>io</code>
 libraries we will use, as you'll see below.
 </p>
 
 <p>
-The <code>page</code> struct describes how page data will be stored in memory. 
+The <code>Page</code> struct describes how page data will be stored in memory. 
 But what about persistent storage? We can address that by creating a 
-<code>save</code> method on <code>page</code>:
+<code>save</code> method on <code>Page</code>:
 </p>
 
 <pre>
@@ -100,13 +100,13 @@ But what about persistent storage? We can address that by creating a
 
 <p>
 This method's signature reads: "This is a method named <code>save</code> that
-takes as its receiver <code>p</code>, a pointer to <code>page</code> . It takes
+takes as its receiver <code>p</code>, a pointer to <code>Page</code> . It takes
 no parameters, and returns a value of type <code>os.Error</code>." 
 </p>
 
 <p>
-This method will save the <code>page</code>'s <code>body</code> to a text 
-file. For simplicity, we will use the <code>title</code> as the file name.
+This method will save the <code>Page</code>'s <code>Body</code> to a text 
+file. For simplicity, we will use the <code>Title</code> as the file name.
 </p>
 
 <p>
@@ -114,7 +114,7 @@ The <code>save</code> method returns an <code>os.Error</code> value because
 that is the return type of <code>WriteFile</code> (a standard library function
 that writes a byte slice to a file).  The <code>save</code> method returns the
 error value, to let the application handle it should anything go wrong while
-writing the file.  If all goes well, <code>page.save()</code> will return
+writing the file.  If all goes well, <code>Page.save()</code> will return
 <code>nil</code> (the zero-value for pointers, interfaces, and some other 
 types).
 </p>
@@ -136,8 +136,8 @@ We will want to load pages, too:
 
 <p>
 The function <code>loadPage</code> constructs the file name from
-<code>title</code>, reads the file's contents into a new
-<code>page</code>, and returns a pointer to that new <code>page</code>.
+<code>Title</code>, reads the file's contents into a new
+<code>Page</code>, and returns a pointer to that new <code>page</code>.
 </p>
 
 <p>
@@ -151,7 +151,7 @@ error return value (in essence, assigning the value to nothing).
 <p>
 But what happens if <code>ReadFile</code> encounters an error?  For example,
 the file might not exist. We should not ignore such errors.  Let's modify the
-function to return <code>*page</code> and <code>os.Error</code>.
+function to return <code>*Page</code> and <code>os.Error</code>.
 </p>
 
 <pre>
@@ -160,7 +160,7 @@ function to return <code>*page</code> and <code>os.Error</code>.
 
 <p>
 Callers of this function can now check the second parameter; if it is
-<code>nil</code> then it has successfully loaded a page. If not, it will be an
+<code>nil</code> then it has successfully loaded a Page. If not, it will be an
 <code>os.Error</code> that can be handled by the caller (see the <a
 href="http://golang.org/pkg/os/#Error">os package documentation</a> for 
 details).
@@ -179,7 +179,7 @@ written:
 <p>
 After compiling and executing this code, a file named <code>TestPage.txt</code>
 would be created, containing the contents of <code>p1</code>. The file would
-then be read into the struct <code>p2</code>, and its <code>body</code> element
+then be read into the struct <code>p2</code>, and its <code>Body</code> element
 printed to the screen.
 </p>
 
@@ -334,7 +334,7 @@ href="http://localhost:8080/view/test">http://localhost:8080/view/test</a></code
 should show a page titled "test" containing the words "Hello world".
 </p>
 
-<h2>Editing pages</h2>
+<h2>Editing Pages</h2>
 
 <p>
 A wiki is not a wiki without the ability to edit pages. Let's create two new
@@ -353,7 +353,7 @@ First, we add them to <code>main()</code>:
 
 <p>
 The function <code>editHandler</code> loads the page 
-(or, if it doesn't exist, create an empty <code>page</code> struct), 
+(or, if it doesn't exist, create an empty <code>Page</code> struct), 
 and displays an HTML form.
 </p>
 
@@ -413,15 +413,15 @@ The function <code>template.ParseFile</code> will read the contents of
 
 <p>
 The method <code>t.Execute</code> replaces all occurrences of 
-<code>{title}</code> and <code>{body}</code> with the values of 
-<code>p.title</code> and <code>p.body</code>, and writes the resultant
+<code>{Title}</code> and <code>{Body}</code> with the values of 
+<code>p.Title</code> and <code>p.Body</code>, and writes the resultant
 HTML to the <code>http.ResponseWriter</code>.
 </p>
 
 <p>
-Note that we've used <code>{body|html}</code> in the above template.  
+Note that we've used <code>{Body|html}</code> in the above template.  
 The <code>|html</code> part asks the template engine to pass the value
-<code>body</code> through the <code>html</code> formatter before outputting it,
+<code>Body</code> through the <code>html</code> formatter before outputting it,
 which escapes HTML characters (such as replacing <code>&gt;</code> with 
 <code>&amp;gt;</code>). 
 This will prevent user data from corrupting the form HTML. 
@@ -472,8 +472,8 @@ The handlers are now shorter and simpler.
 <p>
 What if you visit <code>/view/APageThatDoesntExist</code>? The program will 
 crash. This is because it ignores the error return value from
-<code>loadPage</code>. Instead, if the requested page doesn't exist, it should 
-redirect the client to the edit page so the content may be created:
+<code>loadPage</code>. Instead, if the requested Page doesn't exist, it should 
+redirect the client to the edit Page so the content may be created:
 </p>
 
 <pre>
@@ -486,7 +486,7 @@ The <code>http.Redirect</code> function adds an HTTP status code of
 header to the HTTP response.
 </p>
 
-<h2>Saving pages</h2>
+<h2>Saving Pages</h2>
 
 <p>
 The function <code>saveHandler</code> will handle the form submission. 
@@ -498,7 +498,7 @@ The function <code>saveHandler</code> will handle the form submission.
 
 <p>
 The page title (provided in the URL) and the form's only field, 
-<code>body</code>, are stored in a new <code>page</code>. 
+<code>Body</code>, are stored in a new <code>Page</code>. 
 The <code>save()</code> method is then called to write the data to a file,
 and the client is redirected to the <code>/view/</code> page.
 </p>
@@ -506,7 +506,7 @@ and the client is redirected to the <code>/view/</code> page.
 <p>
 The value returned by <code>FormValue</code> is of type <code>string</code>.
 We must convert that value to <code>[]byte</code> before it will fit into 
-the <code>page</code> struct.  We use <code>[]byte(body)</code> to perform
+the <code>Page</code> struct.  We use <code>[]byte(body)</code> to perform
 the conversion.
 </p>
 
@@ -610,7 +610,7 @@ Then we can create a global variable to store our validation regexp:
 </p>
 
 <pre>
-!./srcextract.bin -src=final-noclosure.go -name=titleValidator
+!./srcextract.bin -src=final-noclosure.go -name=TitleValidator
 </pre>
 
 <p>
@@ -624,7 +624,7 @@ the expression compilation fails, while <code>Compile</code> returns an
 
 <p>
 Now, let's write a function that extracts the title string from the request 
-URL, and tests it against our <code>titleValidator</code> expression:
+URL, and tests it against our <code>TitleValidator</code> expression:
 </p>
 
 <pre>
@@ -708,7 +708,7 @@ The closure returned by <code>makeHandler</code> is a function that takes
 an <code>http.ResponseWriter</code> and <code>http.Request</code> (in other
 words, an <code>http.HandlerFunc</code>). 
 The closure extracts the <code>title</code> from the request path, and
-validates it with the <code>titleValidator</code> regexp. If the
+validates it with the <code>TitleValidator</code> regexp. If the
 <code>title</code> is invalid, an error will be written to the
 <code>ResponseWriter</code> using the <code>http.NotFound</code> function. 
 If the <code>title</code> is valid, the enclosed handler function
index 0cd129253c2c23321704d655ca10e9f2035a84bc..9d7b02f9f95fdc2eb17d893df5527b465d9b2420 100755 (executable)
@@ -103,6 +103,9 @@ if [[ $(uname | tr A-Z a-z | sed 's/mingw/windows/') != *windows* ]]; then
 fi
 ) || exit $?
 
+(xcd ../doc/codelab/wiki
+gomake test) || exit $?
+
 for i in ../misc/dashboard/builder ../misc/goplay
 do
        (xcd $i