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 Editing {title}
+Editing {Title}
-
diff --git a/doc/codelab/wiki/final-noclosure.go b/doc/codelab/wiki/final-noclosure.go
index 2f48565ca..99121f298 100644
--- a/doc/codelab/wiki/final-noclosure.go
+++ b/doc/codelab/wiki/final-noclosure.go
@@ -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)
diff --git a/doc/codelab/wiki/final-noerror.go b/doc/codelab/wiki/final-noerror.go
index cf4852265..0f18912d2 100644
--- a/doc/codelab/wiki/final-noerror.go
+++ b/doc/codelab/wiki/final-noerror.go
@@ -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)
diff --git a/doc/codelab/wiki/final-parsetemplate.go b/doc/codelab/wiki/final-parsetemplate.go
index f02d116b2..ea8977601 100644
--- a/doc/codelab/wiki/final-parsetemplate.go
+++ b/doc/codelab/wiki/final-parsetemplate.go
@@ -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)
diff --git a/doc/codelab/wiki/final-template.go b/doc/codelab/wiki/final-template.go
index 0bb133d3a..4d6a2cfab 100644
--- a/doc/codelab/wiki/final-template.go
+++ b/doc/codelab/wiki/final-template.go
@@ -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)
}
diff --git a/doc/codelab/wiki/final.go b/doc/codelab/wiki/final.go
index 0c0206bc0..8ecd97d74 100644
--- a/doc/codelab/wiki/final.go
+++ b/doc/codelab/wiki/final.go
@@ -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)
diff --git a/doc/codelab/wiki/get.go b/doc/codelab/wiki/get.go
new file mode 100644
index 000000000..342831416
--- /dev/null
+++ b/doc/codelab/wiki/get.go
@@ -0,0 +1,50 @@
+package main
+
+import (
+ "http"
+ "flag"
+ "fmt"
+ "io"
+ "log"
+ "net"
+ "os"
+ "strings"
+)
+
+var (
+ post = flag.String("post", "", "urlencoded form data to POST")
+ addr = flag.Bool("addr", false, "find open address and print to stdout")
+)
+
+func main() {
+ flag.Parse()
+ if *addr {
+ l, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer l.Close()
+ fmt.Print(l.Addr())
+ return
+ }
+ url := flag.Arg(0)
+ if url == "" {
+ log.Fatal("no url supplied")
+ }
+ var r *http.Response
+ var err os.Error
+ if *post != "" {
+ b := strings.NewReader(*post)
+ r, err = http.Post(url, "application/x-www-form-urlencoded", b)
+ } else {
+ r, _, err = http.Get(url)
+ }
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer r.Body.Close()
+ _, err = io.Copy(os.Stdout, r.Body)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/doc/codelab/wiki/htmlify.go b/doc/codelab/wiki/htmlify.go
index 4a52e077f..456d06fd5 100644
--- a/doc/codelab/wiki/htmlify.go
+++ b/doc/codelab/wiki/htmlify.go
@@ -8,5 +8,5 @@ import (
func main() {
b, _ := ioutil.ReadAll(os.Stdin)
- template.HTMLFormatter(os.Stdout, b, "")
+ template.HTMLFormatter(os.Stdout, "", b)
}
diff --git a/doc/codelab/wiki/index.html b/doc/codelab/wiki/index.html
index c494a3ced..fe99c32d1 100644
--- a/doc/codelab/wiki/index.html
+++ b/doc/codelab/wiki/index.html
@@ -71,14 +71,14 @@ declaration.
page
as a struct with two fields representing
+Here, we define Page
as a struct with two fields representing
the title and body.
-type page struct {
- title string
- body []byte
+type Page struct {
+ Title string
+ Body []byte
}
@@ -86,33 +86,33 @@ type page struct {
The type []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.
-The 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
:
-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) }
This method's signature reads: "This is a method named 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
."
-This method will save the 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.
@@ -120,7 +120,7 @@ The 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).
-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} }
The function 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
.
@@ -161,23 +161,23 @@ error return value (in essence, assigning the value to nothing).
But what happens if 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
.
-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 }
Callers of this function can now check the second parameter; if it is
-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).
@@ -191,17 +191,17 @@ written:
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)) }
After compiling and executing this code, a file named 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.
A wiki is not a wiki without the ability to edit pages. Let's create two new @@ -401,7 +401,7 @@ func main() {
The function 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.
edit.html
, and add the following lines:
-<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>@@ -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 = &page{title: title} + p = &Page{Title: title} } t, _ := template.ParseFile("edit.html", nil) t.Execute(p, w) @@ -486,15 +486,15 @@ The function
template.ParseFile
will read the contents of
The method 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
.
-Note that we've used {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.
@@ -511,11 +511,11 @@ While we're working with templates, let's create a template for our
-<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>
@@ -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 = &page{title: title} + p = &Page{Title: title} } renderTemplate(w, "edit", p) } -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) } @@ -568,8 +568,8 @@ The handlers are now shorter and simpler.
What if you visit /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:
@@ -589,7 +589,7 @@ The", - p.title, p.title, p.body) + p.Title, p.Title, p.Body) } func main() { diff --git a/doc/codelab/wiki/part1-noerror.go b/doc/codelab/wiki/part1-noerror.go index 39e8331e3..14cfc321a 100644 --- a/doc/codelab/wiki/part1-noerror.go +++ b/doc/codelab/wiki/part1-noerror.go @@ -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)) } diff --git a/doc/codelab/wiki/part1.go b/doc/codelab/wiki/part1.go index f3678baa5..4b0654f8b 100644 --- a/doc/codelab/wiki/part1.go +++ b/doc/codelab/wiki/part1.go @@ -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)) } diff --git a/doc/codelab/wiki/part2.go b/doc/codelab/wiki/part2.go index 8d4454a74..d57c3a01f 100644 --- a/doc/codelab/wiki/part2.go +++ b/doc/codelab/wiki/part2.go @@ -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, "http.Redirect
function adds an HTTP status code of header to the HTTP response. -Saving pages
+Saving Pages
The function
saveHandler
will handle the form submission. @@ -599,7 +599,7 @@ The functionsaveHandler
will handle the form submission. 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) } @@ -607,7 +607,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) {The page title (provided in the URL) and the form's only field, -
@@ -615,7 +615,7 @@ and the client is redirected to thebody
, are stored in a newpage
. +Body
, are stored in a newPage
. Thesave()
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
@@ -634,7 +634,7 @@ First, let's handle the errors inFormValue
is of typestring
. We must convert that value to[]byte
before it will fit into -thepage
struct. We use[]byte(body)
to perform +thePage
struct. We use[]byte(body)
to perform the conversion.renderTemplate
:-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) @@ -660,7 +660,7 @@ Now let's fix upsaveHandler
: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) @@ -725,7 +725,7 @@ theExecute
method on the appropriateTemplate
fromtemplates
:-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:-var titleValidator = regexp.MustCompile("^[a-zA-Z0-9]+$")@@ -761,7 +760,7 @@ the expression compilation fails, while
Compile
returns anNow, 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 ourTitleValidator
expression:@@ -807,7 +806,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) } @@ -818,7 +817,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) @@ -895,7 +894,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 @@ -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 = &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) diff --git a/doc/codelab/wiki/notemplate.go b/doc/codelab/wiki/notemplate.go index c1f952c83..9cbe9ad76 100644 --- a/doc/codelab/wiki/notemplate.go +++ b/doc/codelab/wiki/notemplate.go @@ -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, "%s
%s", p.title, p.body) + fmt.Fprintf(w, "%s
%s", 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, "Editing %s
"+ "
[edit]
+[edit]
-
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 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
The type []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.
-The 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 aThis method's signature reads: "This is a method named
save
that -takes as its receiverp
, a pointer topage
. It takes +takes as its receiverp
, a pointer toPage
. It takes no parameters, and returns a value of typeos.Error
."-This method will save the
page
'sbody
to a text -file. For simplicity, we will use thetitle
as the file name. +This method will save thePage
'sBody
to a text +file. For simplicity, we will use theTitle
as the file name.@@ -114,7 +114,7 @@ The
@@ -136,8 +136,8 @@ We will want to load pages, too:save
method returns anos.Error
value because that is the return type ofWriteFile
(a standard library function that writes a byte slice to a file). Thesave
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 returnnil
(the zero-value for pointers, interfaces, and some other types).The function
loadPage
constructs the file name from -title
, reads the file's contents into a new -page
, and returns a pointer to that newpage
. +Title
, reads the file's contents into a new +Page
, and returns a pointer to that newpage
.@@ -151,7 +151,7 @@ error return value (in essence, assigning the value to nothing).
But what happens if
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
andos.Error
. +function to return*Page
andos.Error
.@@ -160,7 +160,7 @@ function to return*page
andos.Error
.Callers of this function can now check the second parameter; if it is -
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 anos.Error
that can be handled by the caller (see the os package documentation for details). @@ -179,7 +179,7 @@ written:After compiling and executing this code, a file named
@@ -334,7 +334,7 @@ href="http://localhost:8080/view/test">http://localhost:8080/view/test -TestPage.txt
would be created, containing the contents ofp1
. The file would -then be read into the structp2
, and itsbody
element +then be read into the structp2
, and itsBody
element printed to the screen.Editing pages
+Editing Pages
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
main()
:The function
@@ -413,15 +413,15 @@ The functioneditHandler
loads the page -(or, if it doesn't exist, create an emptypage
struct), +(or, if it doesn't exist, create an emptyPage
struct), and displays an HTML form.template.ParseFile
will read the contents ofThe method
t.Execute
replaces all occurrences of -{title}
and{body}
with the values of -p.title
andp.body
, and writes the resultant +{Title}
and{Body}
with the values of +p.Title
andp.Body
, and writes the resultant HTML to thehttp.ResponseWriter
.-Note that we've used
{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 thehtml
formatter before outputting it, +Body
through thehtml
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.What if you visit
/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 @@ Thehttp.Redirect
function adds an HTTP status code of header to the HTTP response. -Saving pages
+Saving Pages
The function
saveHandler
will handle the form submission. @@ -498,7 +498,7 @@ The functionsaveHandler
will handle the form submission.The page title (provided in the URL) and the form's only field, -
@@ -506,7 +506,7 @@ and the client is redirected to thebody
, are stored in a newpage
. +Body
, are stored in a newPage
. Thesave()
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
@@ -610,7 +610,7 @@ Then we can create a global variable to store our validation regexp:FormValue
is of typestring
. We must convert that value to[]byte
before it will fit into -thepage
struct. We use[]byte(body)
to perform +thePage
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 anNow, 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 ourTitleValidator
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 diff --git a/doc/devel/release.html b/doc/devel/release.html index ecf125953..f965b5cad 100644 --- a/doc/devel/release.html +++ b/doc/devel/release.html @@ -5,6 +5,220 @@This page summarizes the changes between tagged releases of Go. For full details, see the Mercurial change log.
+2011-02-01
+ ++This release includes significant changes to channel operations and minor +changes to the log package. Your code will require modification if it uses +channels in non-blocking communications or the log package's Exit functions. + +Non-blocking channel operations have been removed from the language. +The equivalent operations have always been possible using a select statement +with a default clause. If a default clause is present in a select, that clause +will execute (only) if no other is ready, which allows one to avoid blocking on +a communication. + +For example, the old non-blocking send operation, + + if ch <- v { + // sent + } else { + // not sent + } + +should be rewritten as, + + select { + case ch <- v: + // sent + default: + // not sent + } + +Similarly, this receive, + + v, ok := <-ch + if ok { + // received + } else { + // not received + } + +should be rewritten as, + + select { + case v := <-ch: + // received + default: + // not received + } + +This change is a prelude to redefining the 'comma-ok' syntax for a receive. +In a later release, a receive expression will return the received value and an +optional boolean indicating whether the channel has been closed. These changes +are being made in two stages to prevent this semantic change from silently +breaking code that uses 'comma-ok' with receives. +There are no plans to have a boolean expression form for sends. + +Sends to a closed channel will panic immediately. Previously, an unspecified +number of sends would fail silently before causing a panic. + +The log package's Exit, Exitf, and Exitln functions have been renamed Fatal, +Fatalf, and Fatalln respectively. This brings them in line with the naming of +the testing package. + +The port to the "tiny" operating system has been removed. It is unmaintained +and untested. It was a toy to show that Go can run on raw hardware and it +served its purpose. The source code will of course remain in the repository +history, so it could be brought back if needed later. + +This release also changes some of the internal structure of the memory +allocator in preparation for other garbage collector changes. +If you run into problems, please let us know. +There is one known issue that we are aware of but have not debugged yet: + http://code.google.com/p/go/issues/detail?id=1464&. + +Other changes in this release: +* 5l: document -F, force it on old ARMs (software floating point emulation) +* 6g: fix registerization of temporaries (thanks Eoghan Sherry), + fix uint64(uintptr(unsafe.Pointer(&x))). +* 6l: Relocate CMOV* instructions (thanks Gustavo Niemeyer), + windows/amd64 port (thanks Wei Guangjing). +* 8l: add PE dynexport, emit DWARF in Windows PE, and + code generation fixes (thanks Wei Guangjing). +* bufio: make Flush a no-op when the buffer is empty. +* bytes: Add Buffer.ReadBytes, Buffer.ReadString (thanks Evan Shaw). +* cc: mode to generate go-code for types and variables. +* cgo: define CGO_CFLAGS and CGO_LDFLAGS in Go files (thanks Gustavo Niemeyer), + windows/386 port (thanks Wei Guangjing). +* codereview: fix windows (thanks Hector Chu), + handle file patterns better, + more ASCII vs. Unicode nonsense. +* crypto/dsa: add support for DSA. +* crypto/openpgp: add s2k. +* crypto/rand: use defer to unlock mutex (thanks Anschel Schaffer-Cohen). +* crypto/rsa: correct docstring for SignPKCS1v15. +* crypto: add package, a common place to store identifiers for hash functions. +* doc/codelab/wiki: update to work with template changes, add to run.bash. +* doc/spec: clarify address operators. +* ebnflint: exit with non-zero status on error. +* encoding/base32: new package (thanks Miek Gieben). +* encoding/line: make it an io.Reader too. +* exec: use custom error for LookPath (thanks Gustavo Niemeyer). +* fmt/doc: define width and precision for strings. +* gc: clearer error for struct == struct, + fix send precedence, + handle invalid name in type switch, + special case code for single-op blocking and non-blocking selects. +* go/scanner: fix build (adjust scanner EOF linecount). +* gob: better debugging, commentary, + make nested interfaces work, + report an error when encoding a non-empty struct with no public fields. +* godoc: full text index for whitelisted non-Go files, + show line numbers for non-go files (bug fix). +* gofmt -r: match(...) arguments may be nil; add missing guards. +* govet: add Panic to the list of functions. +* http: add host patterns (thanks Jose Luis Vázquez González), + follow relative redirect in Get. +* json: handle capital floating point exponent (1E100) (thanks Pieter Droogendijk). +* ld: add -I option to set ELF interpreter, + more robust decoding of reflection type info in generating dwarf. +* lib9: update to Unicode 6.0.0. +* make.bash: stricter selinux test (don't complain unless it is enabled). +* misc/vim: Import/Drop commands (thanks Gustavo Niemeyer), + set 'syntax sync' to a large value (thanks Yasuhiro Matsumoto). +* net: fix race condition in test, + return cname in LookupHost. +* netchan: avoid race condition in test, + fixed documentation for import (thanks Anschel Schaffer-Cohen). +* os: add ETIMEDOUT (thanks Albert Strasheim). +* runtime: generate Go defs for C types, + implementation of callback functions for windows (thanks Alex Brainman), + make Walk web browser example work (thanks Hector Chu), + make select fairer, + prefer fixed stack allocator over general memory allocator, + simpler heap map, memory allocation. +* scanner: fix Position returned by Scan, Pos, + don't read ahead in Init. +* suffixarray: use binary search for both ends of Lookup (thanks Eric Eisner). +* syscall: add missing network interface constants (thanks Mikio Hara). +* template: treat map keys as zero, not non-existent (thanks Roger Peppe). +* time: allow cancelling of After events (thanks Roger Peppe), + support Solaris zoneinfo directory. +* token/position: added SetLinesForContent. +* unicode: update to unicode 6.0.0. +* unsafe: add missing case to doc for Pointer. ++ +2011-01-20
+ ++This release removes the float and complex types from the language. + +The default type for a floating point literal is now float64, and +the default type for a complex literal is now complex128. + +Existing code that uses float or complex must be rewritten to +use explicitly sized types. + +The two-argument constructor cmplx is now spelled complex. ++ +2011-01-19
+ ++The 5g (ARM) compiler now has registerization enabled. If you discover it +causes bugs, use 5g -N to disable the registerizer and please let us know. + +The xml package now allows the extraction of nested XML tags by specifying +struct tags of the form "parent>child". See the XML documentation for an +example: http://golang.org/pkg/xml/ + +* 5a, 5l, 6a, 6l, 8a, 8l: handle out of memory, large allocations (thanks Jeff R. Allen). +* 8l: pe changes (thanks Alex Brainman). +* arm: fixes and improvements. +* cc: fix vlong condition. +* cgo: add complex float, complex double (thanks Sebastien Binet), + in _cgo_main.c define all provided symbols as functions. +* codereview: don't mail change lists with no files (thanks Ryan Hitchman). +* crypto/cipher: add OFB mode. +* expvar: add Float. +* fmt: document %X of string, []byte. +* gc, runtime: make range on channel safe for multiple goroutines. +* gc: fix typed constant declarations (thanks Anthony Martin). +* go spec: adjust language for constant typing. +* go/scanner: Make Init take a *token.File instead of a *token.FileSet. +* godoc: bring back "indexing in progress" message, + don't double HTML-escape search result snippets, + enable qualified identifiers ("math.Sin") as query strings again, + peephole optimization for generated HTML, + remove tab before formatted section. +* gofmt, go/printer: do not insert extra line breaks where they may break the code. +* http: fix Content-Range and Content-Length in response (thanks Clement Skau), + fix scheme-relative URL parsing; add ParseRequestURL, + handle HEAD requests correctly, + support for relative URLs. +* math: handle denormalized numbers in Frexp, Ilogb, Ldexp, and Logb (thanks Eoghan Sherry). +* net, syscall: return source address in Recvmsg (thanks Albert Strasheim). +* net: add LookupAddr (thanks Kyle Lemons), + add unixpacket (thanks Albert Strasheim), + avoid nil dereference if /etc/services can't be opened (thanks Corey Thomasson), + implement windows timeout (thanks Wei Guangjing). +* netchan: do not block sends; implement flow control (thanks Roger Peppe). +* regexp: reject bare '?'. (thanks Ben Lynn) +* runtime/cgo: don't define crosscall2 in dummy _cgo_main.c. +* runtime/debug: new package for printing stack traces from a running goroutine. +* runtime: add per-pause gc stats, + fix arm reflect.call boundary case, + print signal information during panic. +* spec: specify that int and uint have the same size. +* syscall: correct WSTOPPED on OS X, + correct length of GNU/Linux abstract Unix domain sockaddr, + correct length of SockaddrUnix. +* tutorial: make stdin, stdout, stderr work on Windows. +* windows: implement exception handling (thanks Hector Chu). ++2011-01-12
@@ -118,16 +332,16 @@ outstanding cgo issues were resolved.Package crypto/cipher has been started, to replace crypto/block. -As part of the changes, rc4.Cipher’s XORKeyStream method signature has changed from +As part of the changes, rc4.Cipher's XORKeyStream method signature has changed from XORKeyStream(buf []byte) to XORKeyStream(dst, src []byte) -to implement the cipher.Stream interface. If you use crypto/block, you’ll need +to implement the cipher.Stream interface. If you use crypto/block, you'll need to switch to crypto/cipher once it is complete. -Package smtp’s StartTLS now takes a *tls.Config argument. +Package smtp's StartTLS now takes a *tls.Config argument. -Package reflect’s ArrayCopy has been renamed to Copy. There are new functions +Package reflect's ArrayCopy has been renamed to Copy. There are new functions Append and AppendSlice. The print/println bootstrapping functions now write to standard error. @@ -261,7 +475,7 @@ will fail to compile rather than behave erroneously. The bytes package has changed. Its Add and AddByte functions have been removed, as their functionality is provided by the recently-introduced built-in function -“append”. Any code that uses them will need to be changed: +"append". Any code that uses them will need to be changed: s = bytes.Add(s, b) -> s = append(s, b...) s = bytes.AddByte(b, c) -> s = append(s, b) s = bytes.Add(nil, c) -> append([]byte(nil), c) @@ -286,8 +500,8 @@ or and the fields are passed as successive arguments to the formatter, by analogy to fmt.Print. -The utf8 package has changed. The order of EncodeRune’s arguments has been -reversed to satisfy the convention of “destination first”. +The utf8 package has changed. The order of EncodeRune's arguments has been +reversed to satisfy the convention of "destination first". Any code that uses EncodeRune will need to be updated. Other changes: @@ -425,12 +639,12 @@ to address both of these deficiencies. The syntax for arrays, slices, and maps of composite literals has been simplified. Within a composite literal of array, slice, or map type, elements that are themselves composite literals may elide the type if it is identical to -the outer literal’s element type. For example, these expressions: +the outer literal's element type. For example, these expressions: [][]int{[]int{1, 2, 3}, []int{4, 5}} - map[string]Point{“x”: Point{1.5, -3.5}, “y”: Point{0, 0}} + map[string]Point{"x": Point{1.5, -3.5}, "y": Point{0, 0}} can be simplified to: [][]int{{1, 2, 3}, {4, 5}} - map[string]Point{“x”: {1.5, -3.5}, “y”: {0, 0}} + map[string]Point{"x": {1.5, -3.5}, "y": {0, 0}} Gofmt can make these simplifications mechanically when invoked with the new -s flag. @@ -446,8 +660,8 @@ The gob package can now encode and decode interface values containing types registered ahead of time with the new Register function. These changes required a backwards-incompatible change to the wire format. Data written with the old version of the package will not be readable with the new one, and vice versa. -(Steps were made in this change to make sure this doesn’t happen again.) -We don’t know of anyone using gobs to create permanent data, but if you do this +(Steps were made in this change to make sure this doesn't happen again.) +We don't know of anyone using gobs to create permanent data, but if you do this and need help converting, please let us know, and do not update to this release yet. We will help you convert your data. @@ -543,7 +757,7 @@ For full details, see the change description: The language change is that uses of pointers to interface values no longer automatically dereference the pointer. A pointer to an interface value is more -often a beginner’s bug than correct code. +often a beginner's bug than correct code. The package exp/iterable has been removed. It was an interesting experiment, but it encourages writing inefficient code and has outlived its utility. diff --git a/doc/devel/roadmap.html b/doc/devel/roadmap.html index 021ed6478..9a3c4eaba 100644 --- a/doc/devel/roadmap.html +++ b/doc/devel/roadmap.html @@ -58,8 +58,6 @@ Implement goto restrictions.
-func Sum(a *[3]float) (sum float) { +func Sum(a *[3]float64) (sum float64) { for _, v := range *a { sum += v } return } -array := [...]float{7.0, 8.5, 9.1} +array := [...]float64{7.0, 8.5, 9.1} x := Sum(&array) // Note the explicit address-of operator@@ -1233,7 +1233,8 @@ Maps are a convenient and powerful built-in data structure to associate values of different types. The key can be of any type for which the equality operator is defined, such as integers, -floats, strings, pointers, and interfaces (as long as the dynamic type +floating point and complex numbers, +strings, pointers, and interfaces (as long as the dynamic type supports equality). Structs, arrays and slices cannot be used as map keys, because equality is not defined on those types. Like slices, maps are a reference type. If you pass a map to a function @@ -1652,7 +1653,7 @@ correctness of the program state before real execution begins.
func init() { if USER == "" { - log.Exit("$USER not set") + log.Fatal("$USER not set") } if HOME == "" { HOME = "/usr/" + USER @@ -1806,7 +1807,7 @@ Because the two types (Sequence
and[]int
) are the same if we ignore the type name, it's legal to convert between them. The conversion doesn't create a new value, it just temporarily acts as though the existing value has a new type. -(There are other legal conversions, such as from integer to float, that +(There are other legal conversions, such as from integer to floating point, that do create a new value.)@@ -2525,39 +2526,49 @@ var serverChan = make(chan *Buffer) func client() { for { - b, ok := <-freeList // grab a buffer if available - if !ok { // if not, allocate a new one + var b *Buffer + // Grab a buffer if available; allocate if not. + select { + case b = <-freeList: + // Got one; nothing more to do. + default: + // None free, so allocate a new one. b = new(Buffer) } - load(b) // read next message from the net - serverChan <- b // send to server + load(b) // Read next message from the net. + serverChan <- b // Send to server. } }
-The server loop receives messages from the client, processes them, +The server loop receives each message from the client, processes it, and returns the buffer to the free list.
func server() { for { - b := <-serverChan // wait for work + b := <-serverChan // Wait for work. process(b) - _ = freeList <- b // reuse buffer if room + // Reuse buffer if there's room. + select { + case freeList <- b: + // Buffer on free list; nothing more to do. + default: + // Free list full, just carry on. + } } }
-The client's non-blocking receive from freeList
obtains a
-buffer if one is available; otherwise the client allocates
-a fresh one.
-The server's non-blocking send on freeList puts b
back
+The client attempts to retrieve a buffer from freeList
;
+if none is available, it allocates a fresh one.
+The server's send to freeList
puts b
back
on the free list unless the list is full, in which case the
buffer is dropped on the floor to be reclaimed by
the garbage collector.
-(The assignment of the send operation to the blank identifier
-makes it non-blocking but ignores whether
-the operation succeeded.)
+(The default
clauses in the select
+statements execute when no other case is ready,
+meaning that the selects
never block.)
This implementation builds a leaky bucket free list
in just a few lines, relying on the buffered channel and
the garbage collector for bookkeeping.
@@ -2860,7 +2871,7 @@ func main() {
http.Handle("/", http.HandlerFunc(QR))
err := http.ListenAndServe(*addr, nil)
if err != nil {
- log.Exit("ListenAndServe:", err)
+ log.Fatal("ListenAndServe:", err)
}
}
diff --git a/doc/gccgo_install.html b/doc/gccgo_install.html
index 393e57963..2ab6dcdae 100644
--- a/doc/gccgo_install.html
+++ b/doc/gccgo_install.html
@@ -296,8 +296,8 @@ than one value, the C function returns a struct. For example, these
functions have equivalent types:
-func GoFunction(int) (int, float) -struct { int i; float f; } CFunction(int) +func GoFunction(int) (int, float64) +struct { int i; float64 f; } CFunction(int)
diff --git a/doc/go_faq.html b/doc/go_faq.html
index 1c7b85ef8..3f9c1d246 100644
--- a/doc/go_faq.html
+++ b/doc/go_faq.html
@@ -665,11 +665,16 @@ of Effective Go for more details.
Why is int
32 bits on 64 bit machines?
-The size of int
and float
is implementation-specific.
+The sizes of int
and uint
are implementation-specific
+but the same as each other on a given platform.
The 64 bit Go compilers (both 6g and gccgo) use a 32 bit representation for
-both int
and float
. Code that relies on a particular
-size of value should use an explicitly sized type, like int64
or
-float64
.
+int
. Code that relies on a particular
+size of value should use an explicitly sized type, like int64
.
+On the other hand, floating-point scalars and complex
+numbers are always sized: float32
, complex64
,
+etc., because programmers should be aware of precision when using
+floating-point numbers.
+The default size of a floating-point constant is float64
.
for _, v := range values { - go func(u) { + go func(u string) { fmt.Println(u) done <- true }(v) diff --git a/doc/go_for_cpp_programmers.html b/doc/go_for_cpp_programmers.html index fae2ec44e..608ab147b 100644 --- a/doc/go_for_cpp_programmers.html +++ b/doc/go_for_cpp_programmers.html @@ -107,7 +107,7 @@ parentheses.@@ -3174,7 +3124,7 @@ yields a function value representingvar ( i int - m float + m float64 )diff --git a/doc/go_spec.html b/doc/go_spec.html index e1c7e90e2..4e5d9c639 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,5 +1,5 @@ - +-Except in a communications clause of a select statement, -sending or receiving from a
@@ -3104,6 +3053,7 @@ need to be presented regarding send, receive, select, and goroutines. ---> +nil
channel causes a +Receiving from anil
channel causes a run-time panic.Method expressions
@@ -3128,8 +3078,8 @@ Consider a struct type
T
with two methods, type T struct { a int } -func (tv T) Mv(a int) int { return 0 } // value receiver -func (tp *T) Mp(f float) float { return 1 } // pointer receiver +func (tv T) Mv(a int) int { return 0 } // value receiver +func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver var t T
Mp
with signature
-func(tp *T, f float) float +func(tp *T, f float32) float32
@@ -3422,14 +3372,14 @@ result is an untyped complex constant.
Complex constants are always constructed from
constant expressions involving imaginary
literals or constants derived from them, or calls of the built-in function
-cmplx
.
+complex
.
const Σ = 1 - 0.707i const Δ = Σ + 2.0e-4 - 1/1i const Φ = iota * 1i -const iΓ = cmplx(0, Γ) +const iΓ = complex(0, Γ)
@@ -3525,7 +3475,7 @@ Statement = FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt | DeferStmt . -SimpleStmt = EmptyStmt | ExpressionStmt | IncDecStmt | Assignment | ShortVarDecl . +SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl . @@ -3553,14 +3503,14 @@ Label = identifier .
-Error: log.Crash("error encountered") +Error: log.Panic("error encountered")
-Function calls, method calls, and channel operations +Function calls, method calls, and receive operations can appear in statement context.
@@ -3570,11 +3520,44 @@ ExpressionStmt = Expression .-f(x+y) +h(x+y) +f.Close() <-ch+
+A send statement sends a value on a channel. +The channel expression must be of channel type +and the type of the value must be assignable +to the channel's element type. +
+ ++SendStmt = Channel "<-" Expression . +Channel = Expression . ++ +
+Both the channel and the value expression are evaluated before communication +begins. Communication blocks until the send can proceed, at which point the +value is transmitted on the channel. +A send on an unbuffered channel can proceed if a receiver is ready. +A send on a buffered channel can proceed if there is room in the buffer. +
+ ++ch <- 3 ++ +
+Sending to a nil
channel causes a
+run-time panic.
+
@@ -3680,8 +3663,8 @@ In assignments, each value must be
assignable to the type of the
operand to which it is assigned. If an untyped constant
is assigned to a variable of interface type, the constant is converted
-to type bool
, int
, float
,
-complex
or string
+to type bool
, int
, float64
,
+complex128
or string
respectively, depending on whether the value is a boolean, integer, floating-point,
complex, or string constant.
SelectStmt = "select" "{" { CommClause } "}" . CommClause = CommCase ":" { Statement ";" } . -CommCase = "case" ( SendExpr | RecvExpr) | "default" . -SendExpr = Expression "<-" Expression . -RecvExpr = [ Expression ( "=" | ":=" ) ] "<-" Expression . +CommCase = "case" ( SendStmt | RecvStmt ) | "default" . +RecvStmt = [ Expression ( "=" | ":=" ) ] RecvExpr . +RecvExpr = Expression .+
-For all the send and receive expressions in the "select"
+RecvExpr must be a receive operation.
+For all the cases in the "select"
statement, the channel expressions are evaluated in top-to-bottom order, along with
-any expressions that appear on the right hand side of send expressions.
+any expressions that appear on the right hand side of send statements.
A channel may be nil
,
which is equivalent to that case not
being present in the select statement
@@ -4126,6 +4113,7 @@ in the "select" statement.
If multiple cases can proceed, a pseudo-random fair choice is made to decide
which single communication will execute.
+ The receive case may declare a new variable using a short variable declaration.
@@ -4138,6 +4126,14 @@ case i1 = <-c1: print("received ", i1, " from c1\n") case c2 <- i2: print("sent ", i2, " to c2\n") + default: print("no communication\n") } @@ -4189,7 +4185,7 @@ func simple_f() int { return 2 } -func complex_f1() (re float, im float) { +func complex_f1() (re float64, im float64) { return -7.0, -4.0 } @@ -4201,7 +4197,7 @@ func complex_f1() (re float, im float) { "return" statement listing these variables, at which point the rules of the previous case apply.-func complex_f2() (re float, im float) { +func complex_f2() (re float64, im float64) { return complex_f1() }@@ -4212,7 +4208,7 @@ func complex_f2() (re float, im float) { and the function may assign values to them as necessary. The "return" statement returns the values of these variables.
-func complex_f3() (re float, im float) { +func complex_f3() (re float64, im float64) { re = 7.0 im = 4.0 return @@ -4391,15 +4387,21 @@ BuiltinCall = identifier "(" [ BuiltinArgs [ "," ] ] ")" . BuiltinArgs = Type [ "," ExpressionList ] | ExpressionList .+
For a channel c
, the built-in function close(c)
marks the channel as unable to accept more values through a send operation;
-values sent to a closed channel are ignored.
+sending to or closing a closed channel causes a run-time panic.
After calling close
, and after any previously
sent values have been received, receive operations will return
the zero value for the channel's type without blocking.
+
+
After at least one such zero value has been
received, closed(c)
returns true.
-type S struct { a int; b float } +type S struct { a int; b float64 } new(S)@@ -4593,29 +4595,28 @@ n3 := copy(b, "Hello, World!") // n3 == 5, b == []byte("Hello")
Three functions assemble and disassemble complex numbers.
-The built-in function cmplx
constructs a complex
+The built-in function complex
constructs a complex
value from a floating-point real and imaginary part, while
real
and imag
extract the real and imaginary parts of a complex value.
-cmplx(realPart, imaginaryPart floatT) complexT +complex(realPart, imaginaryPart floatT) complexT real(complexT) floatT imag(complexT) floatT
The type of the arguments and return value correspond.
-For cmplx
, the two arguments must be of the same
+For complex
, the two arguments must be of the same
floating-point type and the return type is the complex type
with the corresponding floating-point constituents:
-complex
for float
,
complex64
for float32
,
complex128
for float64
.
The real
and imag
functions
together form the inverse, so for a complex value z
,
-z
==
cmplx(real(z),
imag(z))
.
+z
==
complex(real(z),
imag(z))
.
@@ -4624,12 +4625,12 @@ value is a constant.
-var a = cmplx(2, -2) // has type complex -var b = cmplx(1.0, -1.4) // has type complex -x := float32(math.Cos(math.Pi/2)) -var c64 = cmplx(5, -x) // has type complex64 -var im = imag(b) // has type float -var rl = real(c64) // type float32 +var a = complex(2, -2) // complex128 +var b = complex(1.0, -1.4) // complex128 +x := float32(math.Cos(math.Pi/2)) // float32 +var c64 = complex(5, -x) // complex64 +var im = imag(b) // float64 +var rl = real(c64) // float32
-type T struct { i int; f float; next *T } +type T struct { i int; f float64; next *T } t := new(T)diff --git a/doc/go_tutorial.html b/doc/go_tutorial.html index 11e9b4ad7..ece22036a 100644 --- a/doc/go_tutorial.html +++ b/doc/go_tutorial.html @@ -238,14 +238,19 @@ started; for instance,
os.Args
is a slice used by the
-Go has some familiar types such as int
and float
, which represent
+Go has some familiar types such as int
and uint
(unsigned int
), which represent
values of the ''appropriate'' size for the machine. It also defines
explicitly-sized types such as int8
, float64
, and so on, plus
-unsigned integer types such as uint
, uint32
, etc. These are
-distinct types; even if int
and int32
are both 32 bits in size,
+unsigned integer types such as uint
, uint32
, etc.
+These are distinct types; even if int
and int32
are both 32 bits in size,
they are not the same type. There is also a byte
synonym for
uint8
, which is the element type for strings.
+Floating-point types are always sized: float32
and float64
,
+plus complex64
(two float32s
) and complex128
+(two float64s
). Complex numbers are outside the
+scope of this tutorial.
+
Speaking of string
, that's a built-in type as well. Strings are
immutable values—they are not just arrays of byte
values.
Once you've built a string value, you can't change it, although
@@ -452,14 +457,15 @@ language specification but here are some illustrative examples:
a := uint64(0) // equivalent; uses a "conversion"
i := 0x1234 // i gets default type: int
var j int = 1e6 // legal - 1000000 is representable in an int
- x := 1.5 // a float
+ x := 1.5 // a float64, the default type for floating constants
i3div2 := 3/2 // integer division - result is 1
- f3div2 := 3./2. // floating point division - result is 1.5
+ f3div2 := 3./2. // floating-point division - result is 1.5
Conversions only work for simple cases such as converting ints
of one
-sign or size to another, and between ints
and floats
, plus a few other
-simple cases. There are no automatic numeric conversions of any kind in Go,
+sign or size to another and between integers and floating-point numbers,
+plus a couple of other instances outside the scope of a tutorial.
+There are no automatic numeric conversions of any kind in Go,
other than that of making constants have concrete size and type when
assigned to a variable.
@@ -538,9 +544,9 @@ We can use the factory to construct some familiar, exported variables of type
@@ -663,7 +669,7 @@ something from the directory of installed packages.
(Also, ''
-Now we can compile and run the program:
+Now we can compile and run the program. On Unix, this would be the result:
24 var (
-25 Stdin = newFile(0, "/dev/stdin")
-26 Stdout = newFile(1, "/dev/stdout")
-27 Stderr = newFile(2, "/dev/stderr")
+25 Stdin = newFile(syscall.Stdin, "/dev/stdin")
+26 Stdout = newFile(syscall.Stdout, "/dev/stdout")
+27 Stderr = newFile(syscall.Stderr, "/dev/stderr")
28 )
file.go
'' must be compiled before we can import the
package.)
$ 6g file.go # compile file package
diff --git a/doc/go_tutorial.txt b/doc/go_tutorial.txt
index 9c08bd278..5eea3c980 100644
--- a/doc/go_tutorial.txt
+++ b/doc/go_tutorial.txt
@@ -189,14 +189,19 @@ started; for instance, "os.Args" is a slice used by the
An Interlude about Types
----
-Go has some familiar types such as "int" and "float", which represent
+Go has some familiar types such as "int" and "uint" (unsigned "int"), which represent
values of the ''appropriate'' size for the machine. It also defines
explicitly-sized types such as "int8", "float64", and so on, plus
-unsigned integer types such as "uint", "uint32", etc. These are
-distinct types; even if "int" and "int32" are both 32 bits in size,
+unsigned integer types such as "uint", "uint32", etc.
+These are distinct types; even if "int" and "int32" are both 32 bits in size,
they are not the same type. There is also a "byte" synonym for
"uint8", which is the element type for strings.
+Floating-point types are always sized: "float32" and "float64",
+plus "complex64" (two "float32s") and "complex128"
+(two "float64s"). Complex numbers are outside the
+scope of this tutorial.
+
Speaking of "string", that's a built-in type as well. Strings are
immutable values—they are not just arrays of "byte" values.
Once you've built a string value, you can't change it, although
@@ -362,13 +367,14 @@ language specification but here are some illustrative examples:
a := uint64(0) // equivalent; uses a "conversion"
i := 0x1234 // i gets default type: int
var j int = 1e6 // legal - 1000000 is representable in an int
- x := 1.5 // a float
+ x := 1.5 // a float64, the default type for floating constants
i3div2 := 3/2 // integer division - result is 1
- f3div2 := 3./2. // floating point division - result is 1.5
+ f3div2 := 3./2. // floating-point division - result is 1.5
Conversions only work for simple cases such as converting "ints" of one
-sign or size to another, and between "ints" and "floats", plus a few other
-simple cases. There are no automatic numeric conversions of any kind in Go,
+sign or size to another and between integers and floating-point numbers,
+plus a couple of other instances outside the scope of a tutorial.
+There are no automatic numeric conversions of any kind in Go,
other than that of making constants have concrete size and type when
assigned to a variable.
@@ -482,7 +488,7 @@ something from the directory of installed packages.
(Also, ''"file.go"'' must be compiled before we can import the
package.)
-Now we can compile and run the program:
+Now we can compile and run the program. On Unix, this would be the result:
$ 6g file.go # compile file package
$ 6g helloworld3.go # compile main package
diff --git a/doc/htmlgen.go b/doc/htmlgen.go
index 4bed9ed73..5d0bad8b5 100644
--- a/doc/htmlgen.go
+++ b/doc/htmlgen.go
@@ -50,7 +50,7 @@ func read() {
break
}
if err != nil {
- log.Exit(err)
+ log.Fatal(err)
}
n := len(lines)
lines = lines[0 : n+1]
diff --git a/doc/install.html b/doc/install.html
index 92b099fe8..5917da964 100644
--- a/doc/install.html
+++ b/doc/install.html
@@ -45,11 +45,10 @@ architectures.