From 758ff64c69e34965f8af5b2d6ffd65e8d7ab2150 Mon Sep 17 00:00:00 2001
From: Ondřej Surý
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
The type
-The
This method's signature reads: "This is a method named
-This method will save the
@@ -114,7 +114,7 @@ The
The function
@@ -151,7 +151,7 @@ error return value (in essence, assigning the value to nothing).
But what happens if
Callers of this function can now check the second parameter; if it is
-
After compiling and executing this code, a file named
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
The function
The method
-Note that we've used
What if you visit page
as a struct with two fields representing
+Here, we define Page
as a struct with two fields representing
the title and body.
-!./srcextract.bin -src=part1.go -name=page
+!./srcextract.bin -src=part1.go -name=Page
[]byte
means "a byte
slice".
(See Effective Go
for more on slices.)
-The body
element is a []byte
rather than
+The Body
element is a []byte
rather than
string
because that is the type expected by the io
libraries we will use, as you'll see below.
page
struct describes how page data will be stored in memory.
+The Page
struct describes how page data will be stored in memory.
But what about persistent storage? We can address that by creating a
-save
method on page
:
+save
method on Page
:
@@ -100,13 +100,13 @@ But what about persistent storage? We can address that by creating a
save
that
-takes as its receiver p
, a pointer to page
. It takes
+takes as its receiver p
, a pointer to Page
. It takes
no parameters, and returns a value of type os.Error
."
page
's body
to a text
-file. For simplicity, we will use the title
as the file name.
+This method will save the Page
's Body
to a text
+file. For simplicity, we will use the Title
as the file name.
save
method returns an os.Error
value because
that is the return type of WriteFile
(a standard library function
that writes a byte slice to a file). The save
method returns the
error value, to let the application handle it should anything go wrong while
-writing the file. If all goes well, page.save()
will return
+writing the file. If all goes well, Page.save()
will return
nil
(the zero-value for pointers, interfaces, and some other
types).
loadPage
constructs the file name from
-title
, reads the file's contents into a new
-page
, and returns a pointer to that new page
.
+Title
, reads the file's contents into a new
+Page
, and returns a pointer to that new page
.
ReadFile
encounters an error? For example,
the file might not exist. We should not ignore such errors. Let's modify the
-function to return *page
and os.Error
.
+function to return *Page
and os.Error
.
@@ -160,7 +160,7 @@ function to return
*page
and os.Error
.
nil
then it has successfully loaded a page. If not, it will be an
+nil
then it has successfully loaded a Page. If not, it will be an
os.Error
that can be handled by the caller (see the os package documentation for
details).
@@ -179,7 +179,7 @@ written:
TestPage.txt
would be created, containing the contents of p1
. The file would
-then be read into the struct p2
, and its body
element
+then be read into the struct p2
, and its Body
element
printed to the screen.
Editing pages
+Editing Pages
main()
:
editHandler
loads the page
-(or, if it doesn't exist, create an empty page
struct),
+(or, if it doesn't exist, create an empty Page
struct),
and displays an HTML form.
template.ParseFile
will read the contents of
t.Execute
replaces all occurrences of
-{title}
and {body}
with the values of
-p.title
and p.body
, and writes the resultant
+{Title}
and {Body}
with the values of
+p.Title
and p.Body
, and writes the resultant
HTML to the http.ResponseWriter
.
{body|html}
in the above template.
+Note that we've used {Body|html}
in the above template.
The |html
part asks the template engine to pass the value
-body
through the html
formatter before outputting it,
+Body
through the html
formatter before outputting it,
which escapes HTML characters (such as replacing >
with
>
).
This will prevent user data from corrupting the form HTML.
@@ -472,8 +472,8 @@ The handlers are now shorter and simpler.
/view/APageThatDoesntExist
? The program will
crash. This is because it ignores the error return value from
-loadPage
. Instead, if the requested page doesn't exist, it should
-redirect the client to the edit page so the content may be created:
+loadPage
. Instead, if the requested Page doesn't exist, it should
+redirect the client to the edit Page so the content may be created:
@@ -486,7 +486,7 @@ The
http.Redirect
function adds an HTTP status code of
header to the HTTP response.
The function saveHandler
will handle the form submission.
@@ -498,7 +498,7 @@ The function saveHandler
will handle the form submission.
The page title (provided in the URL) and the form's only field,
-body
, are stored in a new page
.
+Body
, are stored in a new Page
.
The save()
method is then called to write the data to a file,
and the client is redirected to the /view/
page.
/view/
page.
The value returned by FormValue
is of type string
.
We must convert that value to []byte
before it will fit into
-the page
struct. We use []byte(body)
to perform
+the Page
struct. We use []byte(body)
to perform
the conversion.
-!./srcextract.bin -src=final-noclosure.go -name=titleValidator +!./srcextract.bin -src=final-noclosure.go -name=TitleValidator
@@ -624,7 +624,7 @@ the expression compilation fails, while Compile
returns an
Now, let's write a function that extracts the title string from the request
-URL, and tests it against our titleValidator
expression:
+URL, and tests it against our TitleValidator
expression:
@@ -708,7 +708,7 @@ The closure returned bymakeHandler
is a function that takes anhttp.ResponseWriter
andhttp.Request
(in other words, anhttp.HandlerFunc
). The closure extracts thetitle
from the request path, and -validates it with thetitleValidator
regexp. If the +validates it with theTitleValidator
regexp. If thetitle
is invalid, an error will be written to theResponseWriter
using thehttp.NotFound
function. If thetitle
is valid, the enclosed handler function -- cgit v1.2.3